Created
March 29, 2020 22:08
-
-
Save nasser/e103624176ed0274f179f87859bcb677 to your computer and use it in GitHub Desktop.
arz parser generator example
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Simple Arithmetics Grammar | |
* ========================== | |
* | |
* Accepts expressions like "2 * (3 + 4)" and computes their value. | |
*/ | |
Expression | |
= head:Term tail:(_ ("+" / "-") _ Term)* { | |
var result = head, i; | |
for (i = 0; i < tail.length; i++) { | |
if (tail[i][1] === "+") { result += tail[i][3]; } | |
if (tail[i][1] === "-") { result -= tail[i][3]; } | |
} | |
return result; | |
} | |
Term | |
= head:Factor tail:(_ ("*" / "/") _ Factor)* { | |
var result = head, i; | |
for (i = 0; i < tail.length; i++) { | |
if (tail[i][1] === "*") { result *= tail[i][3]; } | |
if (tail[i][1] === "/") { result /= tail[i][3]; } | |
} | |
return result; | |
} | |
Factor | |
= "(" _ expr:Expression _ ")" { return expr; } | |
/ Integer | |
Integer "integer" | |
= [0-9]+ { return parseInt(text(), 10); } | |
_ "whitespace" | |
= [ \t\n\r]* |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// this file was generated by the arz parser generator | |
/// probably don't edit it by hand | |
/// take care of each other | |
module Generated | |
open System.Text.RegularExpressions | |
type SourceReader (source:string) = | |
member val position = 0 with get, set | |
member val source = source | |
type ArzLiteral = ArzLiteral of string | |
let peek (sr:SourceReader) = | |
if sr.position < sr.source.Length | |
then sr.source.[sr.position] | |
else (char -1) | |
let position (sr:SourceReader) = | |
sr.position | |
let reset (sr:SourceReader) position' = | |
sr.position <- position' | |
let advance (sr:SourceReader) = | |
reset sr (sr.position+1) | |
let read sr = | |
let c = peek sr | |
advance sr | |
c | |
let readString sr length = | |
let mutable s = "" | |
for _ in 0..length do | |
s <- s + (string (read sr)) | |
s | |
let expect sr c = | |
let p = position sr | |
if read sr = c | |
then Some c | |
else reset sr p; None | |
let expectMatch (pattern:Regex) sr = | |
let p = position sr | |
let c = read sr | |
if c <> '\uffff' && pattern.IsMatch (string c) | |
then Some c | |
else reset sr p; None | |
let expectMatchString sr (pattern:Regex) minimum = | |
let p = position sr | |
let rec readString s = | |
match expectMatch pattern sr with | |
| Some c -> readString (s + (string c)) | |
| None -> s | |
match readString "" with | |
| s when s.Length > minimum -> Some s | |
| _ -> reset sr p; None | |
let expectAny sr (s:string) = | |
let p = position sr | |
let cs = Set.ofArray (s.ToCharArray()) | |
let c = read sr | |
if Set.contains c cs | |
then Some (string c) | |
else reset sr p; None | |
let expectString sr (s:string) = | |
let p = position sr | |
let s' = readString sr (s.Length-1) | |
if s' = s | |
then Some s' | |
else reset sr p; None | |
let expectLiteral sr (s:string) = | |
match expectString sr s with | |
| Some s' -> Some (ArzLiteral s') | |
| _ -> None | |
let parseList sr minimum parsef = | |
let p = position sr | |
let rec readList list = | |
match parsef sr with | |
| Some x -> readList (List.append list [x]) | |
| None -> list | |
match readList [] with | |
| list when List.length list >= minimum -> Some list | |
| _ -> reset sr p; None | |
/// START GENERATED GRAMMAR /// | |
type Expression = Expression of head:Term * tail:ExpressionTail | |
and ExpressionTail = ExpressionTailExpression list | |
and ExpressionTailExpression = ExpressionTailExpression of ExpressionTailExpressionElement2 * Term | |
and ExpressionTailExpressionElement2 = | |
| ExpressionTailExpressionElement2Case0 of ArzLiteral | |
| ExpressionTailExpressionElement2Case1 of ArzLiteral | |
and Term = Term of head:Factor * tail:TermTail | |
and TermTail = TermTailExpression list | |
and TermTailExpression = TermTailExpression of TermTailExpressionElement2 * Factor | |
and TermTailExpressionElement2 = | |
| TermTailExpressionElement2Case0 of ArzLiteral | |
| TermTailExpressionElement2Case1 of ArzLiteral | |
and Factor = | |
| FactorCase1 of FactorCase1 | |
| Integer of Integer | |
and FactorCase1 = FactorCase1 of expr:Expression | |
and Integer = string | |
and Whitespace = string | |
let rec Expression (sr:SourceReader) : Expression option = | |
let p = position sr | |
let var0 = Term sr | |
if Option.isNone var0 then | |
reset sr p; None | |
else | |
let var1 = Expression_tail sr | |
if Option.isNone var1 then | |
reset sr p; None | |
else | |
Some (Expression.Expression (Option.get var0,Option.get var1)) | |
and Expression_tail (sr:SourceReader) : ExpressionTail option = | |
let p = position sr | |
let rec readList list = | |
match Expression_tail_expression sr with | |
| Some next -> readList (List.append list [next]) | |
| None -> list | |
match readList [] with | |
| list when List.length list >= 0 -> Some list | |
| _ -> | |
reset sr p | |
None | |
and Expression_tail_expression (sr:SourceReader) : ExpressionTailExpression option = | |
let p = position sr | |
let var0 = underscore sr | |
if Option.isNone var0 then | |
reset sr p; None | |
else | |
let var1 = Expression_tail_expression_element2 sr | |
if Option.isNone var1 then | |
reset sr p; None | |
else | |
let var2 = underscore sr | |
if Option.isNone var2 then | |
reset sr p; None | |
else | |
let var3 = Term sr | |
if Option.isNone var3 then | |
reset sr p; None | |
else | |
Some (ExpressionTailExpression.ExpressionTailExpression (Option.get var1,Option.get var3)) | |
and Expression_tail_expression_element2 (sr:SourceReader) : ExpressionTailExpressionElement2 option = | |
let p = position sr | |
match expectLiteral sr "+" with | |
| Some x -> Some (ExpressionTailExpressionElement2.ExpressionTailExpressionElement2Case0 x) | |
| _ -> | |
reset sr p | |
match expectLiteral sr "-" with | |
| Some x -> Some (ExpressionTailExpressionElement2.ExpressionTailExpressionElement2Case1 x) | |
| _ -> | |
reset sr p | |
None | |
and Term (sr:SourceReader) : Term option = | |
let p = position sr | |
let var0 = Factor sr | |
if Option.isNone var0 then | |
reset sr p; None | |
else | |
let var1 = Term_tail sr | |
if Option.isNone var1 then | |
reset sr p; None | |
else | |
Some (Term.Term (Option.get var0,Option.get var1)) | |
and Term_tail (sr:SourceReader) : TermTail option = | |
let p = position sr | |
let rec readList list = | |
match Term_tail_expression sr with | |
| Some next -> readList (List.append list [next]) | |
| None -> list | |
match readList [] with | |
| list when List.length list >= 0 -> Some list | |
| _ -> | |
reset sr p | |
None | |
and Term_tail_expression (sr:SourceReader) : TermTailExpression option = | |
let p = position sr | |
let var0 = underscore sr | |
if Option.isNone var0 then | |
reset sr p; None | |
else | |
let var1 = Term_tail_expression_element2 sr | |
if Option.isNone var1 then | |
reset sr p; None | |
else | |
let var2 = underscore sr | |
if Option.isNone var2 then | |
reset sr p; None | |
else | |
let var3 = Factor sr | |
if Option.isNone var3 then | |
reset sr p; None | |
else | |
Some (TermTailExpression.TermTailExpression (Option.get var1,Option.get var3)) | |
and Term_tail_expression_element2 (sr:SourceReader) : TermTailExpressionElement2 option = | |
let p = position sr | |
match expectLiteral sr "*" with | |
| Some x -> Some (TermTailExpressionElement2.TermTailExpressionElement2Case0 x) | |
| _ -> | |
reset sr p | |
match expectLiteral sr "/" with | |
| Some x -> Some (TermTailExpressionElement2.TermTailExpressionElement2Case1 x) | |
| _ -> | |
reset sr p | |
None | |
and Factor (sr:SourceReader) : Factor option = | |
let p = position sr | |
match Factor_case1 sr with | |
| Some x -> Some (Factor.FactorCase1 x) | |
| _ -> | |
reset sr p | |
match Integer sr with | |
| Some x -> Some (Factor.Integer x) | |
| _ -> | |
reset sr p | |
None | |
and Factor_case1 (sr:SourceReader) : FactorCase1 option = | |
let p = position sr | |
let var0 = expectLiteral sr "(" | |
if Option.isNone var0 then | |
reset sr p; None | |
else | |
let var1 = underscore sr | |
if Option.isNone var1 then | |
reset sr p; None | |
else | |
let var2 = Expression sr | |
if Option.isNone var2 then | |
reset sr p; None | |
else | |
let var3 = underscore sr | |
if Option.isNone var3 then | |
reset sr p; None | |
else | |
let var4 = expectLiteral sr ")" | |
if Option.isNone var4 then | |
reset sr p; None | |
else | |
Some (FactorCase1.FactorCase1 (Option.get var2)) | |
and integer (sr:SourceReader) : Integer option = | |
let p = position sr | |
let pattern = Regex "[0-9]" | |
let rec readString s = | |
match expectMatch pattern sr with | |
| Some c -> readString (s + (string c)) | |
| None -> s | |
match readString "" with | |
| s when s.Length >= 1 -> Some s | |
| _ -> | |
reset sr p | |
None | |
and whitespace (sr:SourceReader) : Whitespace option = | |
let p = position sr | |
let pattern = Regex "[ \t\n | |
]" | |
let rec readString s = | |
match expectMatch pattern sr with | |
| Some c -> readString (s + (string c)) | |
| None -> s | |
match readString "" with | |
| s when s.Length >= 0 -> Some s | |
| _ -> | |
reset sr p | |
None | |
/// END GENERATED GRAMMAR /// | |
let parse s = | |
let sr = SourceReader s | |
start sr | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment