Start moving from locals to params.
Chris Pressey
1 year, 10 months ago
15 | 15 | grammar describe the concrete structure of tokens. |
16 | 16 | |
17 | 17 | Grammar ::= {Production}. |
18 | Production ::= NonTerminal "::=" {"local" Variable ":"} {Expr0}. | |
18 | Production ::= NonTerminal [Formals] "::=" {Expr0}. | |
19 | 19 | Expr0 ::= Expr1 {"|" Expr1}. |
20 | 20 | Expr1 ::= Term {Term}. |
21 | 21 | Term ::= "{" Expr0 "}" |
22 | 22 | | "(" Expr0 ")" |
23 | 23 | | "<." Constraint ".>" |
24 | 24 | | Terminal |
25 | | NonTerminal. | |
25 | | NonTerminal [Actuals]. | |
26 | Formals ::= "<" Variable {"," Variable} ">". | |
27 | Actuals ::= "<" VarExpr {"," VarExpr} ">". | |
28 | VarExpr ::= Variable | IntLit. | |
26 | 29 | Constraint ::= Variable Constrainer. |
27 | 30 | Constrainer ::= "=" (Variable | IntLit) |
28 | 31 | | "+=" IntLit |
29 | 32 | | "-=" IntLit |
30 | 33 | | ">" IntLit |
31 | 34 | | "<" IntLit. |
32 | NonTerminal ::= <<upper>><<alphanumeric>>* | |
33 | Terminal ::= <<">><<any>>+<<">> | |
35 | NonTerminal ::= <<upper>><<alphanumeric>>*. | |
36 | Terminal ::= <<">><<any except ">>+<<">>. | |
34 | 37 | |
35 | 38 | The Tests |
36 | 39 | --------- |
120 | 123 | <=== aaabbccc |
121 | 124 | ???> Failure |
122 | 125 | |
123 | ### Parsing with local variables | |
126 | ### Parsing with parameters | |
124 | 127 | |
125 | Goal ::= "Hi" Sp "there" Sp "world" "!"; | |
126 | Sp ::= local n: <. n = 0 .> { " " <. n += 1 .> } <. n > 0 .>; | |
128 | Goal ::= "Hi" Sp<a> "there" Sp<b> "world" "!"; | |
129 | Sp<n> ::= <. n = 0 .> { " " <. n += 1 .> } <. n > 0 .>; | |
127 | 130 | <=== Hi there world! |
128 | 131 | ===> Success |
129 | 132 | |
130 | Goal ::= "Hi" Sp "there" Sp "world" "!"; | |
131 | Sp ::= local n: <. n = 0 .> { " " <. n += 1 .> } <. n > 0 .>; | |
133 | Goal ::= "Hi" Sp<a> "there" Sp<b> "world" "!"; | |
134 | Sp<n> ::= <. n = 0 .> { " " <. n += 1 .> } <. n > 0 .>; | |
132 | 135 | <=== Hi there world! |
133 | 136 | ===> Success |
134 | 137 | |
135 | Goal ::= "Hi" Sp "there" Sp "world" "!"; | |
136 | Sp ::= local n: <. n = 0 .> { " " <. n += 1 .> } <. n > 0 .>; | |
138 | Goal ::= "Hi" Sp<a> "there" Sp<b> "world" "!"; | |
139 | Sp<n> ::= <. n = 0 .> { " " <. n += 1 .> } <. n > 0 .>; | |
137 | 140 | <=== Hi thereworld! |
138 | 141 | ???> Failure |
139 | 142 |
43 | 43 | ; |
44 | 44 | ===> Grammar [("Goal",[],Alt [Seq [Constraint (UnifyConst (Var "a") 0),Loop (Alt [Seq [Terminal 'a',Constraint (Inc (Var "a") 1)]]) [],Constraint (UnifyVar (Var "a") (Var "n")),Constraint (UnifyConst (Var "b") 0),Loop (Alt [Seq [Terminal 'b',Constraint (Inc (Var "b") 1)]]) [],Constraint (UnifyVar (Var "b") (Var "n")),Constraint (UnifyConst (Var "c") 0),Loop (Alt [Seq [Terminal 'c',Constraint (Inc (Var "c") 1)]]) [],Constraint (UnifyVar (Var "c") (Var "n"))]])] |
45 | 45 | |
46 | Locals and multiple productions. | |
46 | Parameters and multiple productions. | |
47 | 47 | |
48 | Goal ::= "Hi" Sp "there" Sp "!"; | |
49 | Sp ::= local n: { " " <. n += 1 .> } <. n > 0 .>; | |
50 | ===> Grammar [("Goal",[],Alt [Seq [Seq [Terminal 'H',Terminal 'i'],NonTerminal "Sp",Seq [Terminal 't',Terminal 'h',Terminal 'e',Terminal 'r',Terminal 'e'],NonTerminal "Sp",Terminal '!']]),("Sp",[Var "n"],Alt [Seq [Loop (Alt [Seq [Terminal ' ',Constraint (Inc (Var "n") 1)]]) [],Constraint (GreaterThan (Var "n") 0)]])] | |
48 | Goal ::= "Hi" Sp<a> "there" Sp<b> "world" "!"; | |
49 | Sp<n> ::= <. n = 0 .> { " " <. n += 1 .> } <. n > 0 .>; | |
50 | ===> Grammar [("Goal",[],Alt [Seq [Seq [Terminal 'H',Terminal 'i'],NonTerminal "Sp",Seq [Terminal 't',Terminal 'h',Terminal 'e',Terminal 'r',Terminal 'e'],NonTerminal "Sp",Seq [Terminal 'w',Terminal 'o',Terminal 'r',Terminal 'l',Terminal 'd'],Terminal '!']]),("Sp",[Var "n"],Alt [Seq [Constraint (UnifyConst (Var "n") 0),Loop (Alt [Seq [Terminal ' ',Constraint (Inc (Var "n") 1)]]) [],Constraint (GreaterThan (Var "n") 0)]])] | |
51 | 51 | |
52 | 52 | ### Preprocessing |
53 | 53 |
24 | 24 | startSymbol (Grammar ((term, _, _) : _)) = term |
25 | 25 | startSymbol (Grammar []) = error "No productions in grammar" |
26 | 26 | |
27 | production nt (Grammar ((term, locals, expr) : rest)) = | |
27 | production nt (Grammar ((term, formals, expr) : rest)) = | |
28 | 28 | if term == nt then expr else production nt (Grammar rest) |
29 | 29 | production nt (Grammar []) = error ("Production '" ++ nt ++ "' not found") |
12 | 12 | |
13 | 13 | prod = do |
14 | 14 | nt <- capWord |
15 | p <- option [] formals | |
15 | 16 | keyword "::=" |
16 | l <- many local | |
17 | 17 | e <- expr0 |
18 | 18 | keyword ";" |
19 | return (nt, l, e) | |
19 | return (nt, p, e) | |
20 | 20 | |
21 | local = do | |
22 | keyword "local" | |
23 | v <- variable | |
24 | keyword ":" | |
21 | formals = do | |
22 | keyword "<" | |
23 | v <- sepBy (variable) (keyword ",") | |
24 | keyword ">" | |
25 | 25 | return v |
26 | 26 | |
27 | 27 | expr0 = do |
102 | 102 | |
103 | 103 | nonterminal = do |
104 | 104 | s <- capWord |
105 | a <- option [] actuals | |
105 | 106 | return $ NonTerminal s |
107 | ||
108 | actuals = do | |
109 | keyword "<" | |
110 | v <- sepBy (variable) (keyword ",") | |
111 | keyword ">" | |
112 | return v | |
106 | 113 | |
107 | 114 | -- |
108 | 115 | -- Low level: Concrete things |
8 | 8 | preprocessGrammar :: Grammar -> Grammar |
9 | 9 | preprocessGrammar (Grammar productions) = |
10 | 10 | let |
11 | productions' = map (\(term, locals, expr) -> (term, locals, preprocessExpr expr)) productions | |
11 | productions' = map (\(term, formals, expr) -> (term, formals, preprocessExpr expr)) productions | |
12 | 12 | in |
13 | 13 | Grammar productions' |
14 | 14 |