-
Notifications
You must be signed in to change notification settings - Fork 9
Example Pascal
In the example/pascal folder development started by writing a manual implementation for the embryonal Pascal example, pascal.cs, taking into account this could be generated. The output of the example program, parses the example Pascal file and outputs an AST-like structure.
The example Pascal program, taken from the EBNF Wikipedia page, looks like this:
PROGRAM DEMO1
BEGIN
A:=3;
B:=45;
H:=-100023;
C:=A;
D123:=B34A;
BABOON:=GIRAFFE;
TEXT:="Hello world!";
END.The Manual target of the build file compiles the manual implementation and runs it, producing a string-representation of the resulting AST:
$ cd example/pascal
$ xbuild /target:Manual
XBuild Engine Version 14.0
Mono, Version 4.6.2.0
Copyright (C) 2005-2013 Various Mono authors
Build started 3/6/2017 12:57:17 PM.
__________________________________________________
Project "/Users/xtof/Workspace/human-parser-generator/example/pascal/pascal.csproj" (Manual target(s)):
Target Manual:
Tool /Library/Frameworks/Mono.framework/Versions/4.6.2/lib/mono/4.5/mcs.exe execution started with arguments: /debug+ /out:bin/Debug/pascal-manual.exe ../../generator/parsable.cs ../../generator/dump-ast.cs pascal-manual.cs /target:exe
Executing: mono bin/Debug/pascal-manual.exe example.pascal | LC_ALL="C" astyle -s2 -xt0 -xe -Y -xC80
new Program() {
Identifier = new Identifier() { Name = "DEMO1"},
Assignments = new List<Assignment>() {
new Assignment() {
Identifier = new Identifier() { Name = "A"},
Expression = new Number() {
Value = "3"
}
},new Assignment() {
Identifier = new Identifier() { Name = "B"},
Expression = new Number() {
Value = "45"
}
},new Assignment() {
Identifier = new Identifier() { Name = "H"},
Expression = new Number() {
Value = "-100023"
}
},new Assignment() {
Identifier = new Identifier() { Name = "C"},
Expression = new Identifier() {
Name = "A"
}
},new Assignment() {
Identifier = new Identifier() { Name = "D123"},
Expression = new Identifier() {
Name = "B34A"
}
},new Assignment() {
Identifier = new Identifier() { Name = "BABOON"},
Expression = new Identifier() {
Name = "GIRAFFE"
}
},new Assignment() {
Identifier = new Identifier() { Name = "TEXT"},
Expression = new String() {
Text = "Hello world!"
}
}
}
}
Done building project "/Users/xtof/Workspace/human-parser-generator/example/pascal/pascal.csproj".
Build succeeded.
0 Warning(s)
0 Error(s)
Time Elapsed 00:00:00.9019200I've chosen to implement the
ToString()functionality of the AST as C# code that builds the same data structure. This is easy to reuse it, e.g. in unit tests and it formats nicely (using e.g. AStyle).
Next, the build file also implements a generated Pascal parser, from a grammar language definition. This grammar, also acquired from the EBNF Wikipedia page looks like this (after modifications to use the extended possibilities of the [HPG Grammar](HPG Grammar):
(* a simple program syntax in HPG-flavoured EBNF - based on example from Wikipedia *)
program = "PROGRAM" identifier
"BEGIN"
{ assignment ";" }
"END."
;
assignment = identifier ":=" expression ;
expression = identifier
| string
| number
;
identifier = name @ ? /([A-Z][A-Z0-9]*)/ ? ;
string = text @ ? /"([^"]*)"|'([^']*)'/ ? ;
number = value @ ? /(-?[1-9][0-9]*)/ ? ;Issuing xbuild runs the manual implementation, generates a fresh Pascal parser, compares the manual and generated parser and finally also runs the generated version:
$ xbuild
XBuild Engine Version 14.0
Mono, Version 4.6.2.0
Copyright (C) 2005-2013 Various Mono authors
Build started 3/6/2017 1:03:49 PM.
__________________________________________________
Project "/Users/xtof/Workspace/human-parser-generator/example/pascal/pascal.csproj" (default target(s)):
Target Manual:
Tool /Library/Frameworks/Mono.framework/Versions/4.6.2/lib/mono/4.5/mcs.exe execution started with arguments: /debug+ /out:bin/Debug/pascal-manual.exe ../../generator/parsable.cs ../../generator/dump-ast.cs pascal-manual.cs /target:exe
Executing: mono bin/Debug/pascal-manual.exe example.pascal | LC_ALL="C" astyle -s2 -xt0 -xe -Y -xC80
new Program() {
Identifier = new Identifier() { Name = "DEMO1"},
Assignments = new List<Assignment>() {
new Assignment() {
Identifier = new Identifier() { Name = "A"},
Expression = new Number() {
Value = "3"
}
},new Assignment() {
Identifier = new Identifier() { Name = "B"},
Expression = new Number() {
Value = "45"
}
},new Assignment() {
Identifier = new Identifier() { Name = "H"},
Expression = new Number() {
Value = "-100023"
}
},new Assignment() {
Identifier = new Identifier() { Name = "C"},
Expression = new Identifier() {
Name = "A"
}
},new Assignment() {
Identifier = new Identifier() { Name = "D123"},
Expression = new Identifier() {
Name = "B34A"
}
},new Assignment() {
Identifier = new Identifier() { Name = "BABOON"},
Expression = new Identifier() {
Name = "GIRAFFE"
}
},new Assignment() {
Identifier = new Identifier() { Name = "TEXT"},
Expression = new String() {
Text = "Hello world!"
}
}
}
}
Target HPG:
Project "/Users/xtof/Workspace/human-parser-generator/hpg.csproj" (default target(s)):
Target Gen0Parser:
Tool /Library/Frameworks/Mono.framework/Versions/4.6.2/lib/mono/4.5/mcs.exe execution started with arguments: /debug+ /out:bin/Debug/hpg.gen0.exe generator/parsable.cs generator/generator.cs generator/factory.cs generator/emitter.csharp.cs generator/emitter.bnf.cs generator/format.csharp.cs generator/AssemblyInfo.cs generator/grammar.cs generator/bootstrap.cs /target:exe
Target Gen1Source:
Executing: mono bin/Debug/hpg.gen0.exe generator/hpg.bnf | LC_ALL="C" astyle -s2 -xt0 -xe -Y -xC80 > generator/parser.gen1.cs
Target Gen1Parser:
Tool /Library/Frameworks/Mono.framework/Versions/4.6.2/lib/mono/4.5/mcs.exe execution started with arguments: /debug+ /out:bin/Debug/hpg.gen1.exe generator/parsable.cs generator/generator.cs generator/factory.cs generator/emitter.csharp.cs generator/emitter.bnf.cs generator/format.csharp.cs generator/AssemblyInfo.cs generator/parser.gen1.cs generator/hpg.cs /target:exe
Target HPGSource:
Executing: mono bin/Debug/hpg.gen1.exe generator/hpg.bnf | LC_ALL="C" astyle -s2 -xt0 -xe -Y -xC80 > generator/parser.cs
Target Build:
Tool /Library/Frameworks/Mono.framework/Versions/4.6.2/lib/mono/4.5/mcs.exe execution started with arguments: /debug+ /out:bin/Debug/hpg.exe generator/parsable.cs generator/generator.cs generator/factory.cs generator/emitter.csharp.cs generator/emitter.bnf.cs generator/format.csharp.cs generator/AssemblyInfo.cs generator/parser.cs generator/hpg.cs /target:exe
Done building project "/Users/xtof/Workspace/human-parser-generator/hpg.csproj".
Target Generated:
Executing: mono ../../bin/Debug//hpg.exe -i pascal.bnf | LC_ALL="C" astyle -s2 -xt0 -xe -Y -xC80 > pascal.cs
Target Compare:
Executing: cat pascal-manual.cs | LC_ALL="C" astyle -s2 -xt0 -xe -Y -xC80 > manual.cs
Executing: diff -u -w manual.cs pascal.cs
Executing: rm manual.cs
Target BuildGenerated:
Tool /Library/Frameworks/Mono.framework/Versions/4.6.2/lib/mono/4.5/mcs.exe execution started with arguments: /debug+ /out:bin/Debug/parse-pascal.exe ../../generator/parsable.cs ../../generator/dump-ast.cs pascal.cs /target:exe
Target RunGenerated:
Executing: mono bin/Debug/parse-pascal.exe example.pascal | LC_ALL="C" astyle -s2 -xt0 -xe -Y -xC80
new Program() {
Identifier = new Identifier() { Name = "DEMO1"},
Assignments = new List<Assignment>() {
new Assignment() {
Identifier = new Identifier() { Name = "A"},
Expression = new Number() {
Value = "3"
}
},new Assignment() {
Identifier = new Identifier() { Name = "B"},
Expression = new Number() {
Value = "45"
}
},new Assignment() {
Identifier = new Identifier() { Name = "H"},
Expression = new Number() {
Value = "-100023"
}
},new Assignment() {
Identifier = new Identifier() { Name = "C"},
Expression = new Identifier() {
Name = "A"
}
},new Assignment() {
Identifier = new Identifier() { Name = "D123"},
Expression = new Identifier() {
Name = "B34A"
}
},new Assignment() {
Identifier = new Identifier() { Name = "BABOON"},
Expression = new Identifier() {
Name = "GIRAFFE"
}
},new Assignment() {
Identifier = new Identifier() { Name = "TEXT"},
Expression = new String() {
Text = "Hello world!"
}
}
}
}
Done building project "/Users/xtof/Workspace/human-parser-generator/example/pascal/pascal.csproj".
Build succeeded.
0 Warning(s)
0 Error(s)
Time Elapsed 00:00:03.1727410