Skip to content

Instantly share code, notes, and snippets.

@sporkmonger
Created June 14, 2009 15:30
Show Gist options
  • Save sporkmonger/129723 to your computer and use it in GitHub Desktop.
Save sporkmonger/129723 to your computer and use it in GitHub Desktop.
type expr =
Noop
| Int of int
| Float of float
| Seq of expr list
| Call of expr * string * expr (* * params *)
let print_ast ast =
let rec print_ast_internal = function
Noop -> "Noop"
| Int(n) -> (Printf.sprintf "Int %d" n)
| Float(n) -> (Printf.sprintf "Float %f" n)
| Seq(expressions) -> (
String.concat "" [
"Seq(";
String.concat ", " (List.map print_ast_internal expressions);
")"
]
)
| Call(target, message, param) -> (
String.concat "" [
"Call(";
String.concat ", " [
print_ast_internal(target);
message;
print_ast_internal(param)
];
")"
]
)
in (Printf.printf "%s\n" (print_ast_internal ast))
type expr =
Noop
| Int of int
| Float of float
| Seq of expr list
| Call of expr * string * expr (* TODO: * params *)
val print_ast : expr -> unit
%{
(* header *)
open Ast;;
%}
/* declarations */
%token <int> INT
%token <float> FLOAT
%token SEMI
%token PLUS MINUS TIMES DIV
%token LPAREN RPAREN LBRACK RBRACK LBRACE RBRACE
%token EOL
%nonassoc SEMI
%left PLUS MINUS /* low precedence */
%left TIMES DIV /* medium precedence */
%nonassoc UMINUS /* highest precedence */
%start main /* the entry point */
%type <Ast.expr> main
%%
/* rules */
main:
expr EOL { $1 }
;
expr:
INT { Int($1) }
| FLOAT { Float($1) }
| expr SEMI { Seq([$1; Noop]) }
| expr SEMI expr {
match $1 with
Seq(expressions) -> Seq(List.append expressions [$3])
| single_expression -> Seq([single_expression; $3])
}
| LPAREN expr RPAREN { $2 }
| expr PLUS expr { Call($1, "+", $3) }
| expr MINUS expr { Call($1, "-", $3) }
| expr TIMES expr { Call($1, "*", $3) }
| expr DIV expr { Call($1, "/", $3) }
| MINUS expr %prec UMINUS {
match $2 with
Int(value) -> Int(-value)
| Float(value) -> Float(-.value)
| _ -> failwith "Unary minus can only be applied to numeric literals."
}
;
%%
(* trailer *)
{
open Grammar;; (* The type token is defined in grammar.mli *)
exception Eof;;
}
rule token = parse
[' ' '\t'] { token lexbuf } (* skip blanks *)
| ['\n' ] { EOL }
| ['0'-'9']+ as lxm { INT(int_of_string lxm) }
| '+' { PLUS }
| '-' { MINUS }
| '*' { TIMES }
| '/' { DIV }
| '(' { LPAREN }
| ')' { RPAREN }
| '[' { LBRACK }
| ']' { RBRACK }
| '{' { LBRACE }
| '}' { RBRACE }
| ';' { SEMI }
| eof { raise Eof }
let _ =
try
let lexbuf = Lexing.from_channel stdin in
while true do
let result = Grammar.main Lexer.token lexbuf in
Ast.print_ast result; flush stdout
done
with Lexer.Eof ->
exit 0
16 states, 269 transitions, table size 1172 bytes
File "grammar.mly", line 29, characters 30-41:
Error: This expression has type Ast.expr but is here used with type int
File "mindigo.ml", line 6, characters 22-28:
Error: This expression has type int but is here used with type Ast.expr
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment