diff options
author | Robin Haberkorn <robin.haberkorn@googlemail.com> | 2013-12-05 18:39:11 +0100 |
---|---|---|
committer | Robin Haberkorn <robin.haberkorn@googlemail.com> | 2013-12-05 18:39:11 +0100 |
commit | b96a4189d89146cdc6bba5e2c477a42b46f787cd (patch) | |
tree | 8965e9904b8fc1de286fbaa70cb28a46fbedc2e6 /ebnf.sno | |
download | groff-tools-b96a4189d89146cdc6bba5e2c477a42b46f787cd.tar.gz |
initial commit of files from my bachelor-thesis repo
Diffstat (limited to 'ebnf.sno')
-rwxr-xr-x | ebnf.sno | 138 |
1 files changed, 138 insertions, 0 deletions
diff --git a/ebnf.sno b/ebnf.sno new file mode 100755 index 0000000..682be78 --- /dev/null +++ b/ebnf.sno @@ -0,0 +1,138 @@ +#!/usr/local/bin/snobol4 -b + +*** +*** Definitions +*** + define('optspace(pattern)') + define('string()') + define('serialize()') + strings = array(2) + str_no = 0 + + define('emit_groff(str)') + + define('begin_rule()') + define('end_rule()') + + define('emit_nonterm()') + define('emit_term()') + define('emit_empty()') + + define('begin_exp()') + define('end_exp()') + + define('begin_alt()') + define('end_alt()') + define('repeat()') + define('repeat_with()') + + &anchor = 1 + &fullscan = 1 + +*** +*** EBNF grammar +*** + letter = &lcase &ucase + digit = "0123456789" + + space = span(" " char(9) char(10) char(13)) | "" + eol = break(char(10) char(13)) + nonterm = ( "`" break("`") $ *string() "`" ++ | (any(letter) (span(letter digit "_") | "")) $ *string() ) ++ (optspace("~") *nonterm | "") + term = ( "'" break("'") $ *string() "'" ++ | '"' break('"') $ *string() '"' ) ++ (optspace("~") *term | "") + + lhs = nonterm + exp = nonterm *emit_nonterm() ++ | term *emit_term() ++ | optspace("[") *emit_empty() *begin_alt() *rhs optspace("]") *end_alt() ++ | optspace("{") *begin_exp() *rhs optspace("}") *end_exp() ++ (optspace("~") term *repeat_with() | *repeat()) ++ | optspace("(") *begin_exp() *rhs optspace(")") *end_exp() ++ | *emit_empty() + rhs = exp ++ ( optspace("|") *begin_alt() *rhs *end_alt() ++ | optspace(",") *rhs ++ | "") + +* NOTE: have to reset str_no if there is no lhs, since +* strings may already contain a nonterminal + rule = ( lhs optspace("=" | ":=" | "::=") ++ | *?(str_no = 0) "" $ *string() ) ++ *begin_rule() rhs optspace(";") *end_rule() + comment = optspace("(*" breakx("*") "*)" | "#" eol) + groff = optspace("." eol $ str) *emit_groff(str) + pic = optspace("%" eol $ output) + grammar = arbno(comment | groff | pic | rule) rpos(0) + +*** +*** MAIN +*** + lineno = 1 + +loop line = input :f(end) + line ".lf " int . lineno :s(next) + line ".EBNF" :s(src.l) + lineno = lineno + 1 +next output = line :(loop) + +src.l line = input + lineno = lineno + 1 + line ".EBNF" :s(compile) + src = src line char(10) :(src.l) + +compile + output = ".PS" + output = 'copy "syntax.pic";' + (src ? grammar, terminal = "FAILURE") + output = 'reset;' + output = ".PE" + output = ".lf " (lineno + 1) + src = "" :(loop) + +*** +*** Procedures +*** +optspace + optspace = space pattern space :(return) + +string + string = .strings[str_no = str_no + 1] :(nreturn) +serialize +* NOTE: will leave str_no == 0 + serialize = '"' strings[str_no] '" ' serialize + eq(str_no = str_no - 1, 0) :s(return)f(serialize) + +emit_groff + output = 'command ".' str '";' :(return) + +begin_rule + output = 'begin_rule(' serialize() ');' :(return) +end_rule + output = 'end_rule();' :(return) + +emit_nonterm + output = 'nonterminal(' serialize() ');' :(return) +emit_term + output = 'terminal(' serialize() ');' :(return) +emit_empty + output = 'empty();' :(return) + +begin_exp + output = 'begin_group();' :(return) +end_exp + output = 'end_group();' :(return) + +begin_alt + output = 'begin_alt(last []);' :(return) +end_alt + output = 'end_alt(2nd last []);' :(return) + +repeat output = 'repeat(last []);' :(return) +repeat_with + output = 'repeat_with(last [],' serialize() ');' :(return) + +end + |