lex-comment. = extends $(Lexer) level = 0 other: . lex() term: $'[*][)]' if $(not $(eq $(level), 0)) level = $(sub $(level), 1) lex() next: $'[(][*]' level = $(add $(level), 1) lex() eof: $"\'" eprintln(Unterminated comment) lexer1. = extends $(Lexer) other: . eprintln(Illegal character: $0) lex() white: $'[[:space:]]+' lex() comment: $'[(][*]' lex-comment.lex-channel($(channel)) lex() op: $'[-+*/()]' switch $0 case + Token.unit($(loc), plus) case - Token.unit($(loc), minus) case * Token.unit($(loc), mul) case / Token.unit($(loc), div) case $'(' Token.unit($(loc), lparen) case $')' Token.unit($(loc), rparen) number: $'[[:digit:]]+' Token.pair($(loc), exp, $(int $0)) eof: $"\'" Token.unit($(loc), eof) parser1. = extends $(Parser) # # Use the main lexer # lexer = $(lexer1) # # Precedences, in ascending order # left(plus minus) left(mul div) right(uminus) # # A program # start(prog) prog: exp eof value $1 # # Simple arithmetic expressions # exp: minus exp :prec: uminus neg($2) exp: exp plus exp add($1, $3) exp: exp minus exp sub($1, $3) exp: exp mul exp mul($1, $3) exp: exp div exp div($1, $3) exp: lparen exp rparen value $2 println(Test1: should print 48) println(Parsed $(parser1.parse-file prog, Test.input1)) lexer2. = extends $(lexer1) lsl: $"<<" Token.unit($(loc), lsl) lsr: $">>>" Token.unit($(loc), lsr) asr: $">>" Token.unit($(loc), asr) parser2. = extends $(parser1) left(plus, lsl lsr asr) lexer = $(lexer2) exp: exp lsl exp lsl($1, $3) exp: exp lsr exp lsr($1, $3) exp: exp asr exp asr($1, $3) println(Test2: should print 256) println(Parsed $(parser2.parse-file prog, Test.input2))