Vea los ejemplos del directorio para los ejemplos de los programas de
análisis construidos usando Ml-Yacc. Aquí está un programa de análisis y un
lexer pequeños de la muestra para una calculadora interactiva, del directorio
examples/calc, junto con el código para crear una función del análisis. La
calculadora lee unas o más expresiones de la entrada estándar, evalúa las
expresiones, e imprime sus valores. Las expresiones se deben separar por puntos
y comas, y pueden también ser terminadas usando un end-of-file. Esto demuestra
cómo construir un programa de análisis interactivo cuál lee un declaración a
nivel superior y procesa el declaración antes de leer el declaración a nivel
superior siguiente.
(* muestree la calculadora interactiva para Ml-Yacc *) operaciones de búsqueda = 10000 "falsos" de la diversión|operaciones de búsqueda s = 0 %% %eop EOF SEMI (* %pos declara el tipo de posiciones para los terminales. Cada símbolo tiene una posición izquierda y derecha asociada. *) el SUBMARINO interno de %pos %left MÁS %left MIDE EL TIEMPO DE LA identificación del DIV %right CARAT %term de la secuencia|NUMÉRICO de interno|MÁS|ÉPOCAS|IMPRESIÓN|SEMI|Eof|CARAT|Div|%nonterm SECUNDARIO EXP de interno|COMIENZO de la IMPRESIÓN interna de la opción %name Calc %subst para la identificación %prefer MÁS COMIENZO SECUNDARIO de la identificación de la IMPRESIÓN SEMI %noshift EOF %value del DIV %keyword de las ÉPOCAS ("falso") %nodefault %verbose el %% (* el programa de análisis vuelve el valor asociado a la expresión *): IMPRESIÓN EXP (impresión EXP; impresión "\n"; std_out del flush_out; ALGÚN EXP)|EXP (ALGÚN EXP)|(NINGUNOS) EXP: NUMÉRICO (NUMÉRICO)|Identificación (identificación de las operaciones de búsqueda)|EXP MÁS EXP (EXP1+EXP2)|EXP MIDE EL TIEMPO DE EXP (EXP1*EXP2)|EXP DIV EXP (EXP1 div EXP2)|EXP EXP SECUNDARIO (EXP1-exp2)|EXP CARAT EXP (deje la diversión e (m,0) = 1|e (m,l) = m*e(m, l-1) en extremo de e (EXP1, exp2))
estructure el tipo del símbolo = del símbolo posición = svalue interno del tipo = símbolo del tipo de Tokens.svalue (' a, 'b) = (' a, 'b) lexresult del tipo de Tokens.token = (svalue, posición) val simbólico posición = la referencia 0 val eof = fn () = > Tokens.EOF(!pos, error del!pos) = fn val (e,l: interno, _) = > output(std_out, "línea" ^ (l) makestring ^ ": "^ e ^" \n") el %% %header (símbolo de CalcLexFun(structure del functor: Calc_TOKENS)); alpha=[A-Za-z ]; digit=[0-9 ]; W = [ \ \t ]; \n del %% = > (posición: = (!pos) + 1; lex()); { ws}+ = > (lex()); { digit}+ = > (Tokens.NUM (revfold (fn (a,r) = > ord(a)-ord("0")+10*r) (estalle el yytext) 0,!pos,!pos)); "+" = > (Tokens.PLUS(!pos,!pos)); "*" = > (Tokens.TIMES(!pos,!pos)); ";" = > (Tokens.SEMI(!pos,!pos)); { alpha}+ = > (si yytext="print "entonces Tokens.PRINT(!pos,!pos) Tokens.ID(yytext otro,!pos,!pos)); "-" = > (Tokens.SUB(!pos,!pos)); "^" = > (Tokens.CARAT(!pos,!pos)); "/"= > (Tokens.DIV(!pos,!pos)); "." = > (error ("no haciendo caso ^yytext del mal carácter ",!pos,!pos); lex());
Usted debe seguir las instrucciones en la sección de crear los functors del programa de análisis y del lexer y de cargarlos. Después de que usted haya hecho esto, usted debe entonces aplicar los functors para producir la estructura de CalcParser. El código para hacer esto se demuestra abajo.
estructure la estructura CalcLex de CalcLrVals = del símbolo = de LrParser.Token de CalcLrValsFun(structure) = el símbolo de CalcLexFun(structure = CalcLrVals.Tokens); estructure la estructura ParserData de CalcParser = de Join(structure LrParser = de LrParser = la estructura Lex = CalcLex de CalcLrVals.ParserData)
Ahora necesitamos una función que dado un lexer invoque el programa de
análisis. La función invoca
hace esto.
la diversión invoca el lexstream = dejó el print_error de la diversión (s, i:int, _) = TextIO.output(TextIO.stdOut, "error, línea" ^ (Int.toString i) ^ ", "^ s ^" \n") en CalcParser.parse(0, lexstream, print_error, extremo del ())
Finalmente, necesitamos una función que pueda leer unas o más expresiones de
la entrada estándar. La función analiza
, demostrado abajo, hace esto.
Funciona la calculadora en la entrada estándar y termina cuando se encuentra un
end-of-file.
la diversión analiza () = dejó el lexer val = el dummyEOF val de CalcParser.makeLexer (fn _ = > TextIO.inputLine TextIO.stdIn) = CalcLrVals.Tokens.EOF(0,0) dummySEMI val = CalcLrVals.Tokens.SEMI(0,0) lexer del lazo de la diversión = dejó val (resultado, lexer) = invoca el lexer val (nextToken, lexer) = lexer de CalcParser.Stream.get en caso de que resultado de un CIERTO r = > TextIO.output(TextIO.stdOut, "resultado =" ^ (Int.toString r) ^ "\n")|NINGUNOS = > (); si CalcParser.sameToken(nextToken, extremo otro del lexer del lazo del dummyEOF) entonces () en extremo del lexer del lazo