ll1 is a tool that reads in an LL(1) grammar description and checks it, and that, with the help of Go templates can generate code or reports based on those grammars.
Beoran eadef8ac14 Recursive descent parser helper | 2 years ago | |
---|---|---|
ast | 2 years ago | |
cmd | 2 years ago | |
common | 2 years ago | |
flexer | 2 years ago | |
flexgen | 2 years ago | |
generator | 2 years ago | |
grammar | 2 years ago | |
old | 2 years ago | |
parser | 2 years ago | |
rdpar | 2 years ago | |
.gitignore | 4 years ago | |
LICENSE | 4 years ago | |
README.md | 2 years ago | |
bad.ll1 | 4 years ago | |
go.mod | 2 years ago | |
lexer.go | 3 years ago | |
liner | 4 years ago | |
ll1.ll1 | 4 years ago | |
muesli.ll1 | 4 years ago |
ll1 is a tool to parse and check LL(1) specifications, and to generate code or reports using Go templates based on these specifications. ll1 specifications must contain a definition for an ll1 grammar, and may optionally also specify a lexer for that grammar.
ll1 [options] input_file.ll1 [template_file.ext*]
The [options] are:
-append file
Name of output file to append. Takes precedence over -out.
-define definition
Add a definition for the template, in the form of key:value or
[]key:value. Keys that start with a [] are arrays and can be
concatenated to by specifying the same definition key again.
Non array keys will be overwoitten if they are specified again.
-help
Shows the help page.
-out file
Name of output file to overwrite.
-template file
Template file to expand. This may be repeated to make use
of several templates to generate one output file.
-verbose
Be more verbose. Shows the scanned tokens as well.
The names of template files may be given with the -t option, or after the ll1 input file.
The syntax of an LL1 grammar itself is:
Specification -> Grammar OptLexer.
Grammar -> Rules.
Rules -> Rule OptRules .
OptRules -> dot Rules | epsilon.
Rule -> Name arrow Definition Template.
Name -> ruleName .
Template -> rawString | epsilon .
// Alternates consist of sequences.
Definition -> Alternates .
Alternates -> Sequence OptSequences .
OptSequences -> or Alternates | epsilon.
Sequence -> Element OptElements .
OptElements -> Element OptElements | epsilon .
Element -> Parenthesis .
Element -> Name .
Element -> literal .
Parenthesis -> '(' Definition ')' .
OptLexer -> LexerTerminal OptLexerTerminals | epsilon .
LexerTerminal -> terminalName arrow LexerDefinition Template .
LexerDefinition -> LexerAlternates .
LexerAlternates -> LexerPattern OptLexerMatches .
OptLexerMatches -> or LexerPattern | epsilon.
LexerPattern -> literal .
OptElements -> Element OptElements | epsilon .
Element -> Parenthesis .
Element -> Name .
Element -> literal /*| Rule */.
// Lexer specification starts here:
dot -> '.'
or -> '|'
literal -> characterLiteral | stringLiteral
ruleName -> "re:[[:isUpper:]][[:isAlNum]]"
terminalName -> "re:[[:isLower:]][[:isAlNum]]"
epsilon -> "epsilon" | 'ε'
arrow -> "->" | '→'
The syntax of an ll1 grammar has the following elements:
If no templates are given, ll1 simply checks the grammar and outputs a simple text report to the output file.
If a template is given, it will be expanded and output to the output file.
Inside the template the following variables are available:
Inside the ll1 templates, the following template functions are available:
Follow conflict example:
A -> B | C .
B -> D e . C -> e . D -> f | epsilon .
Since D is optional and can be empty, this parser cannot decide between B and C, because in case D is empty, both sides match.