The output from yacc is a Limbo module y.tab.b containing the parse function yyparse which must be provided with a YYLEX adt providing the parser access to a lexical analyser routine lex(), an error routine error(), and any other context required.
The options are
Comments follow the Limbo convention (a # symbol gives a comment until the end of the line).
A %module directive is required, which replaces the %union directive. It is of the form:
A type YYSTYPE must be defined, giving the type associated with yacc tokens. If the angle bracket construction is used after any of the %token, %left, %right, %nonassoc or %type directives in order to associate a type with a token or production, the word inside the angle brackets refers to a member of an instance of YYSTYPE, which should be an adt.
An adt YYLEX must be defined, providing context to the parser. The definition must consist of at least the following:
YYLEX: adt { lval: YYSTYPE; lex: fn(l: self ref YYLEX): int; error: fn(l: self ref YYLEX, msg: string); }Lex should invoke a lexical analyser to return the next token for yacc to analyse. The value of the token should be left in lval. Error will be called when a parse error occurs. Msg is a string describing the error.
Yyparse takes one argument, a reference to the YYLEX adt that will be used to provide it with tokens.
The parser is fully re-entrant; i.e. it does not hold any parse state in any global variables within the module.
%{ include "sys.m"; sys: Sys; include "bufio.m"; bufio: Bufio; Iobuf: import bufio; include "draw.m"; YYSTYPE: adt { v: real; }; YYLEX: adt { lval: YYSTYPE; lex: fn(l: self ref YYLEX): int; error: fn(l: self ref YYLEX, msg: string); }; %} %module Calc{ init: fn(ctxt: ref Draw->Context, args: list of string); } %left '+' '-' %left '*' '/' %type <v> exp uexp term %token <v> REAL %% top : | top '\n' | top exp '\n' { sys->print("%g\n", $2); } | top error '\n' ; exp : uexp | exp '*' exp { $$ = $1 * $3; } | exp '/' exp { $$ = $1 / $3; } | exp '+' exp { $$ = $1 + $3; } | exp '-' exp { $$ = $1 - $3; } ; uexp : term | '+' uexp { $$ = $2; } | '-' uexp { $$ = -$2; } ; term : REAL | '(' exp ')' { $$ = $2; } ; %% in: ref Iobuf; stderr: ref Sys->FD; init(nil: ref Draw->Context, nil: list of string) { sys = load Sys Sys->PATH; bufio = load Bufio Bufio->PATH; in = bufio->fopen(sys->fildes(0), Bufio->OREAD); stderr = sys->fildes(2); lex := ref YYLEX; yyparse(lex); } YYLEX.error(nil: self ref YYLEX, err: string) { sys->fprint(stderr, "%s\n", err); } YYLEX.lex(lex: self ref YYLEX): int { for(;;){ c := in.getc(); case c{ ' ' or '\t' => ; '-' or '+' or '*' or '/' or '\n' or '(' or ')' => return c; '0' to '9' or '.' => s := ""; i := 0; s[i++] = c; while((c = in.getc()) >= '0' && c <= '9' || c == '.' || c == 'e' || c == 'E') s[i++] = c; in.ungetc(); lex.lval.v = real s; return REAL; * => return -1; } } }
YACC(1 ) | Rev: Thu Feb 15 14:42:47 GMT 2007 |