%{
openBasic_types;;
letphrase_of_cmdc=matchcwith"RUN"->Run|"LIST"->List|"END"->End|_->failwith"line : unexpected command"
;;
letbin_op_of_relr=matchrwith"="->EQUAL|"<"->INF|"<="->INFEQ|">"->SUP|">="->SUPEQ|"<>"->DIFF|_->failwith"line : unexpected relation symbol"
;;%}
Lexical units are the following:
Their names are self-explanatory and they are described in file basic_lexer.mll (see page ??).%token<int>Lint%token<string>Lident%token<string>Lstring%token<string>Lcmd%tokenLplusLminusLmultLdivLmod%token<string>Lrel%tokenLandLorLneg%tokenLparRpar%token<string>Lrem%tokenLremLletLprintLinputLifLthenLgoto%tokenLequal%tokenLeol
Precedence rules between operators once again take the values assigned by functions priority_uop and priority_binop defined when first giving the grammar for our Basic (see page ??).
Symbol Lop will be used to process unary minus. It is not a terminal in the grammar, but a ``pseudo non-terminal'' which allows overloading of operators when two uses of an operator should not receive the same precedence depending on context. This is the case with the minus symbol (-). We will reconsider this point once we have specified the rules in the grammar.%rightLneg%leftLandLor%leftLequalLrel%leftLmod%leftLplusLminus%leftLmultLdiv%nonassocLop
Since the start symbol is line, the function generated will return the syntax tree for the parsed line.
%start line %type <Basic_types.phrase> line
These rules do not call for particular remarks except:%%
line:LintinstLeol{Line{num=$1;inst=$2}}|LcmdLeol{phrase_of_cmd$1};
inst:Lrem{Rem$1}|LgotoLint{Goto$2}|Lprintexp{$2}|LinputLident{Input$2}|LifexpLthenLint{If($2,$4)}|LletLidentLequalexp{Let($2,$4)};
exp:Lint{ExpInt$1}|Lident{ExpVar$1}|Lstring{ExpStr$1}|Lnegexp{ExpUnr(NOT,$2)}|expLplusexp{ExpBin($1,PLUS,$3)}|expLminusexp{ExpBin($1,MINUS,$3)}|expLmultexp{ExpBin($1,MULT,$3)}|expLdivexp{ExpBin($1,DIV,$3)}|expLmodexp{ExpBin($1,MOD,$3)}|expLequalexp{ExpBin($1,EQUAL,$3)}|expLrelexp{ExpBin($1,(bin_op_of_rel$2),$3)}|expLandexp{ExpBin($1,AND,$3)}|expLorexp{ExpBin($1,OR,$3)}|Lminusexp%precLop{ExpUnr(OPPOSITE,$2)}|LparexpRpar{$2};%%
exp :
...
| Lminus exp %prec Lop { ExpUnr(OPPOSITE, $2) }
It concerns the use of unary -.
Keyword %prec that we find in it declares that this rule should receive
the precedence of Lop (here the highest precedence).
{openBasic_parser;;letstring_charss=String.subs1((String.lengths)-2);;
}
rulelexer=parse[' ''\t']{lexerlexbuf}|'\n'{Leol}|'!'{Lneg}|'&'{Land}|'|'{Lor}|'='{Lequal}|'%'{Lmod}|'+'{Lplus}|'-'{Lminus}|'*'{Lmult}|'/'{Ldiv}|['<''>']{Lrel(Lexing.lexemelexbuf)}|"<="{Lrel(Lexing.lexemelexbuf)}|">="{Lrel(Lexing.lexemelexbuf)}|"REM"[^'\n']*{Lrem(Lexing.lexemelexbuf)}|"LET"{Llet}|"PRINT"{Lprint}|"INPUT"{Linput}|"IF"{Lif}|"THEN"{Lthen}|"GOTO"{Lgoto}|"RUN"{Lcmd(Lexing.lexemelexbuf)}|"LIST"{Lcmd(Lexing.lexemelexbuf)}|"END"{Lcmd(Lexing.lexemelexbuf)}|['0'-'9']+{Lint(int_of_string(Lexing.lexemelexbuf))}|['A'-'z']+{Lident(Lexing.lexemelexbuf)}|'"'[^'"']*'"'{Lstring(string_chars(Lexing.lexemelexbuf))}
"REM" [^ '\n']*). This rule
recognizes keyword REM followed by an arbitrary number of
characters other than '\n'. The second remark concerns character
strings ('"' [^ '"']* '"') considered as sequences of
characters different from " and contained between two ".ocamlc -c basic_types.mli ocamlyacc basic_parser.mly ocamllex basic_lexer.mll ocamlc -c basic_parser.mli ocamlc -c basic_lexer.ml ocamlc -c basic_parser.mlWhich will generate files basic_lexer.cmo and basic_parser.cmo which may be linked into an application.
withmatchparse(input_linestdin)with
matchlinelexer(Lexing.from_string((input_linestdin)^"\n"))with
'\n' which function input_line had filtered
out. This is necessary because the '\n' character indicates the
end of a command line (Leol).