1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
|
local re = require 'relabel'
local terror = {
cmdSeq = "Missing ';' in CmdSeq",
ifExp = "Error in expresion of 'if'",
ifThen = "Error matching 'then' keyword",
ifThenCmdSeq = "Error matching CmdSeq of 'then' branch",
ifElseCmdSeq = "Error matching CmdSeq of 'else' branch",
ifEnd = "Error matching 'end' keyword of 'if'",
repeatCmdSeq = "Error matching CmdSeq of 'repeat'",
repeatUntil = "Error matching 'until' keyword",
repeatExp = "Error matching expression of 'until'",
assignOp = "Error matching ':='",
assignExp = "Error matching expression of assignment",
readName = "Error matching 'NAME' after 'read'",
writeExp = "Error matching expression after 'write'",
simpleExp = "Error matching 'SimpleExp'",
term = "Error matching 'Term'",
factor = "Error matching 'Factor'",
openParExp = "Error matching expression after '('",
closePar = "Error matching ')'",
eof = "Error, expecting EOF",
undefined = "Undefined Error"
}
g = re.compile([[
Tiny <- CmdSeq (!. / %{eof})
CmdSeq <- (Cmd SEMICOLON^cmdSeq) (Cmd SEMICOLON^cmdSeq)*
Cmd <- IfCmd / RepeatCmd / ReadCmd / WriteCmd / AssignCmd
IfCmd <- IF Exp^ifExp THEN^ifThen CmdSeq^ifThenCmdSeq (ELSE CmdSeq^ifElseCmdSeq / '') END^ifEnd
RepeatCmd <- REPEAT CmdSeq^repeatCmdSeq UNTIL^repeatUntil Exp^repeatExp
AssignCmd <- NAME ASSIGNMENT^assignOp Exp^assignExp
ReadCmd <- READ NAME^readName
WriteCmd <- WRITE Exp^writeExp
Exp <- SimpleExp ((LESS / EQUAL) SimpleExp^simpleExp / '')
SimpleExp <- Term ((ADD / SUB) Term^term)*
Term <- Factor ((MUL / DIV) Factor^factor)*
Factor <- OPENPAR Exp^openParExp CLOSEPAR^closePar / NUMBER / NAME
ADD <- Sp '+'
ASSIGNMENT <- Sp ':='
CLOSEPAR <- Sp ')'
DIV <- Sp '/'
IF <- Sp 'if'
ELSE <- Sp 'else'
END <- Sp 'end'
EQUAL <- Sp '='
LESS <- Sp '<'
MUL <- Sp '*'
NAME <- !RESERVED Sp [a-z]+
NUMBER <- Sp [0-9]+
OPENPAR <- Sp '('
READ <- Sp 'read'
REPEAT <- Sp 'repeat'
SEMICOLON <- Sp ';'
SUB <- Sp '-'
THEN <- Sp 'then'
UNTIL <- Sp 'until'
WRITE <- Sp 'write'
RESERVED <- (IF / ELSE / END / READ / REPEAT / THEN / UNTIL / WRITE) ![a-z]+
Sp <- (%s / %nl)*
]], terror)
local function mymatch(g, s)
local r, e, pos = g:match(s)
if not r then
local line, col = re.calcline(s, pos)
local msg = "Error at line " .. line .. " (col " .. col .. "): "
return r, msg .. terror[e]
end
return r
end
local s = [[
n := 5;
f := 1;
repeat
f := f + n;
n := n - 1
until (n < 1);
write f;]]
print(mymatch(g, s))
s = [[
n := 5;
f := 1;
repeat
f := f + n;
n := n - 1;
until (n < 1);
read ;]]
print(mymatch(g, s))
s = [[
if a < 1 then
b := 2;
else
b := 3;]]
print(mymatch(g, s))
s = [[
n := 5;
f := 1;
repeat
f := f + n;
n := n - 1;
untill (n < 1);
]]
print(mymatch(g, s))
s = [[
n := 5;
f := 1;
repeat
f := f + n;
n := n - 1;
3 (n < 1);
]]
print(mymatch(g, s))
print(mymatch(g, "a : 2"))
print(mymatch(g, "a := 2; 6"))
|