Skip to content

Instantly share code, notes, and snippets.

@nasser
Created March 29, 2020 22:08
Show Gist options
  • Save nasser/e103624176ed0274f179f87859bcb677 to your computer and use it in GitHub Desktop.
Save nasser/e103624176ed0274f179f87859bcb677 to your computer and use it in GitHub Desktop.
arz parser generator example
/*
* 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 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