-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpackrat.sf
131 lines (113 loc) · 4.58 KB
/
packrat.sf
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
124
125
126
127
128
129
130
131
-- Position
type Position = { posFile: String, posLine: Int, posCol: Int };
-- Helpers
let div (a: Int) (b: Int): Int = a / b;
let posLargerThan (a: Position) (b: Position): Bool = a.posLine > b.posLine || (a.posLine == b.posLine && a.posCol > b.posCol);
let showPos (pos: Position): String =
"File: ".concat(pos.posFile).concat(" Line: ").concat(pos.posLine.toString()).concat(" Column: ")
.concat(pos.posCol.toString());
let showPosRel (a: Position) (b: Position): String =
if a.posFile.equals(b.posFile) then
if a.posLine == b.posLine then
"Column: ".concat(b.posCol.toString())
else "Line: ".concat(b.posLine.toString()).concat(" Column: ").concat(b.posCol.toString())
else showPos b;
let nextPos (pos: Position) (c: Char): Position =
if c == '\n' then pos with {posFile = pos.posFile, posLine = pos.posLine + 1, posCol = 1}
else
if c == '\t' then pos with {posFile = pos.posFile, posLine = pos.posLine, posCol = (div (pos.posCol + 7) 8) * 8 + 1}
else
pos with {posFile = pos.posFile, posLine = pos.posLine, posCol = pos.posCol + 1};
-- Data types used for parsing
data Maybe[A] = Nothing
| Just A;
data PolyList[A] = Nil
| Cons A (PolyList[A]);
type CharList = PolyList[Char];
let rec readPolyList(s: String): CharList =
if s.length() == 0 then Nil[Char]
else (Cons[Char] s.charAt(0) (readPolyList(s.substring(1))));
data Result[V] = Parsed V { dvAdditive: Result[Int],
dvMultitive: Result[Int],
dvPrimary: Result[Int],
dvDecimal: Result[Int],
dvChar: Result[Char]
}
| NoParse;
type Derivs = { dvAdditive: Result[Int],
dvMultitive: Result[Int],
dvPrimary: Result[Int],
dvDecimal: Result[Int],
dvChar: Result[Char]
};
let pAdditive: Derivs -> Result[Int] =
\(d: Derivs) -> (case d.dvMultitive of
Parsed vleft d1 ->
(case d1.dvChar of
Parsed c d2 -> if c == '+' then
(case d2.dvAdditive of
Parsed vright d3 -> Parsed[Int] (vleft + vright) d3
| NoParse -> (case d.dvMultitive of
Parsed v d1 -> Parsed[Int] v d1
| NoParse -> NoParse[Int]))
else (case d.dvMultitive of
Parsed v d1 -> Parsed[Int] v d1
| NoParse -> NoParse[Int])
| NoParse -> (case d.dvMultitive of
Parsed v d1 -> Parsed[Int] v d1
| NoParse -> NoParse[Int]))
| NoParse -> (case d.dvMultitive of
Parsed v d1 -> Parsed[Int] v d1
| NoParse -> NoParse[Int]));
let pMultitive: Derivs -> Result[Int] =
\(d: Derivs) -> (case d.dvMultitive of
Parsed vleft d1 ->
(case d1.dvChar of
Parsed c d2 -> if c == '*' then
(case d2.dvMultitive of
Parsed vright d3 -> Parsed[Int] (vleft * vright) d3
| NoParse -> (case d.dvPrimary of
Parsed v d1 -> Parsed[Int] v d1
| NoParse -> NoParse[Int]))
else (case d.dvPrimary of
Parsed v d1 -> Parsed[Int] v d1
| NoParse -> NoParse[Int])
| NoParse -> (case d.dvPrimary of
Parsed v d1 -> Parsed[Int] v d1
| NoParse -> NoParse[Int]))
| NoParse -> (case d.dvPrimary of
Parsed v d1 -> Parsed[Int] v d1
| NoParse -> NoParse[Int]));
let pPrimary: Derivs -> Result[Int] =
\(d: Derivs) -> (case d.dvChar of
Parsed c d1 -> if c == '(' then
(case d1.dvAdditive of
Parsed v d2 ->
(case d2.dvChar of
Parsed c2 d3 -> Parsed[Int] v d3
| NoParse -> (case d.dvDecimal of
Parsed v2 d1 -> Parsed[Int] v2 d1
| NoParse -> NoParse[Int]))
| NoParse -> (case d.dvDecimal of
Parsed v2 d1 -> Parsed[Int] v2 d1
| NoParse -> NoParse[Int]))
else (case d.dvDecimal of
Parsed v2 d1 -> Parsed[Int] v2 d1
| NoParse -> NoParse[Int])
| NoParse -> (case d.dvDecimal of
Parsed v2 d1 -> Parsed[Int] v2 d1
| NoParse -> NoParse[Int]));
-- Parse a decimal digit
let pDecimal: Derivs -> Result[Int] =
\(d: Derivs) -> case d.dvChar of
Parsed v d1 ->
if v >= '0' && v <= '9' then Parsed[Int] java.lang.Character.digit(v, 10) d1
else NoParse[Int]
| NoParse -> NoParse[Int];
let rec parse (cs: CharList): Derivs =
{dvAdditive = pAdditive (parse cs), dvMultitive = pMultitive (parse cs), dvPrimary = pPrimary (parse cs), dvDecimal = pDecimal (parse cs), dvChar = (case cs of Cons x xs -> Parsed[Char] x (parse xs) | Nil -> NoParse[Char])};
let eval (cs: CharList): Int =
case (parse cs).dvAdditive of
Parsed v rem -> v
| NoParse -> error[Int] "Parse error";
showPos({posFile = "hello", posLine = 1, posCol = 2})