Commit 30b6a0e5 authored by POTTIER Francois's avatar POTTIER Francois
Browse files

Modified quicktest/positions/ to construct an AST and print it afterwards.

This allows us not to worry about the order of the printing side effects.
parent 1df3f20b
open Lexing
let print nt startpos endpos =
Printf.printf "%s: startpos = %s/%03d,\n%s: endpos = %s/%03d\n"
nt
startpos.pos_fname
startpos.pos_cnum
nt
endpos.pos_fname
endpos.pos_cnum
type positions =
position * position
type nothing =
positions
type optional_dot =
positions * nothing option
type optional_comma =
positions * nothing option
type annotations =
positions * optional_dot * optional_comma
type raw_expr =
| EInt
| EParen of annotations * nothing * expr * optional_dot
| EBinOp of expr * expr
| EUnOp of expr
and expr =
positions * raw_expr
type main =
positions * nothing * expr
let iter f = function
| None ->
()
| Some x ->
f x
module Print = struct
let positions nt (startpos, endpos) =
Printf.printf "%s: startpos = %s/%03d,\n%s: endpos = %s/%03d\n"
nt
startpos.pos_fname
startpos.pos_cnum
nt
endpos.pos_fname
endpos.pos_cnum
let nothing =
positions "nothing"
let optional_dot (poss, no) =
positions "optional_dot" poss;
iter nothing no
let optional_comma (poss, no) =
positions "optional_comma" poss;
iter nothing no
let annotations (poss, odot, ocomma) =
positions "annotations" poss;
optional_dot odot;
optional_comma ocomma
let rec raw_expr = function
| EInt ->
()
| EParen (a, n, e, o) ->
annotations a;
nothing n;
expr e;
optional_dot o
| EBinOp (e1, e2) ->
expr e1;
expr e2
| EUnOp e ->
expr e
and expr (poss, e) =
positions "expr" poss;
raw_expr e
let main (poss, n, e) =
positions "main" poss;
nothing n;
expr e
end
......@@ -4,8 +4,11 @@ let process (line : string) =
let linebuf = from_string line in
linebuf.lex_curr_p <- { pos_fname = "-"; pos_lnum = 1; pos_bol = 0; pos_cnum = 0 };
try
(* Run the parser on this line of input. *)
Parser.main Lexer.token linebuf
(* Run the parser on this line of input. Print the resulting tree.
We construct a tree and print it afterwards (instead of printing
within the semantic actions) because %inline reorders side effects,
and that would prevent us from comparing the positions. *)
Aux.Print.main (Parser.main Lexer.token linebuf)
with
| Lexer.Error msg ->
Printf.fprintf stderr "%s%!" msg
......
......@@ -8,45 +8,52 @@
%left TIMES DIV /* medium precedence */
%nonassoc UMINUS /* highest precedence */
%start<unit> main
%start<Aux.main> main
%{ open Aux %}
%%
main:
| nothing expr EOL
{}
| n = nothing e = expr EOL
{ ($startpos, $endpos), n, e }
/* Added just to exercise productions with an empty right-hand side. */
%inline nothing:
| /* nothing */
{ Aux.print "nothing" $startpos $endpos }
{ ($startpos, $endpos) }
/* Added just to exercise productions with an empty right-hand side, in a choice. */
optional_dot:
| nothing
| n = nothing
{ ($startpos, $endpos), Some n }
| DOT
{ Aux.print "optional_dot" $startpos $endpos}
{ ($startpos, $endpos), None }
%inline optional_comma:
| nothing
| n = nothing
{ ($startpos, $endpos), Some n }
| COMMA
{ Aux.print "optional_comma" $startpos $endpos}
{ ($startpos, $endpos), None }
annotations:
optional_dot optional_comma
{ Aux.print "annotations" $startpos $endpos }
{ ($startpos, $endpos), $1, $2 }
raw_expr:
| INT
| annotations LPAREN nothing expr RPAREN optional_dot
{ EInt }
| a = annotations LPAREN n = nothing e = expr RPAREN o = optional_dot
{ EParen(a, n, e, o) }
| expr PLUS expr
| expr MINUS expr
| expr TIMES expr
| expr DIV expr
{ EBinOp ($1, $3) }
| MINUS expr %prec UMINUS
{}
{ EUnOp $2 }
expr:
raw_expr
{ Aux.print "expr" $startpos $endpos }
e = raw_expr
{ ($startpos, $endpos), e }
......@@ -8,7 +8,7 @@
%left TIMES DIV /* medium precedence */
%nonassoc UMINUS /* highest precedence */
%type<unit> main
%type<Aux.main> main
%start main
/* For now, we do not use [Parsing.symbol_start_pos()] because it performs
......@@ -17,51 +17,53 @@
[Parsing.symbol_start_pos()] for epsilon productions and
[Parsing.rhs_start_pos 1] for non-epsilon productions. */
%{ open Aux %}
%%
main:
| nothing expr EOL
{}
{ (Parsing.rhs_start_pos 1, Parsing.symbol_end_pos()), $1, $2 }
/* Added just to exercise productions with an empty right-hand side. */
nothing:
| /* nothing */
{ Aux.print "nothing" (Parsing.symbol_start_pos()) (Parsing.symbol_end_pos()) }
{ (Parsing.symbol_start_pos(), Parsing.symbol_end_pos()) }
/* Added just to exercise productions with an empty right-hand side, in a choice. */
optional_dot:
| nothing
{ Aux.print "optional_dot" (Parsing.symbol_start_pos()) (Parsing.symbol_end_pos())}
{ (Parsing.symbol_start_pos(), Parsing.symbol_end_pos()), Some $1 }
| DOT
{ Aux.print "optional_dot" (Parsing.rhs_start_pos 1) (Parsing.symbol_end_pos())}
{ (Parsing.symbol_start_pos(), Parsing.symbol_end_pos()), None }
optional_comma:
| nothing
{ Aux.print "optional_comma" (Parsing.symbol_start_pos()) (Parsing.symbol_end_pos())}
{ (Parsing.symbol_start_pos(), Parsing.symbol_end_pos()), Some $1 }
| COMMA
{ Aux.print "optional_comma" (Parsing.rhs_start_pos 1) (Parsing.symbol_end_pos())}
{ (Parsing.symbol_start_pos(), Parsing.symbol_end_pos()), None }
annotations:
optional_dot optional_comma
{ Aux.print "annotations" (Parsing.rhs_start_pos 1) (Parsing.symbol_end_pos())}
{ (Parsing.rhs_start_pos 1, Parsing.symbol_end_pos()), $1, $2 }
raw_expr:
| INT
{}
{ EInt }
| annotations LPAREN nothing expr RPAREN optional_dot
{}
{ EParen($1, $3, $4, $6) }
| expr PLUS expr
{}
{ EBinOp ($1, $3) }
| expr MINUS expr
{}
{ EBinOp ($1, $3) }
| expr TIMES expr
{}
{ EBinOp ($1, $3) }
| expr DIV expr
{}
{ EBinOp ($1, $3) }
| MINUS expr %prec UMINUS
{}
{ EUnOp $2 }
expr:
raw_expr
{ Aux.print "expr" (Parsing.rhs_start_pos 1) (Parsing.symbol_end_pos()) }
{ (Parsing.rhs_start_pos 1, Parsing.symbol_end_pos()), $1 }
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment