Created
April 15, 2017 22:06
-
-
Save jdh30/de3c157c12396830f439ffbfc7b9ec1a to your computer and use it in GitHub Desktop.
FemtoML parser in F# using fslex and fsyacc
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
open Parse | |
open Lexing | |
let ident = function | |
| "let" -> LET | |
| "rec" -> REC | |
| "in" -> IN | |
| "fun" -> FUN | |
| "if" -> IF | |
| "then" -> THEN | |
| "else" -> ELSE | |
| s -> IDENT s | |
} | |
let digit = ['0'-'9'] | |
let alpha = ['a'-'z' 'A'-'Z']+ | |
let ident = alpha+ (alpha | digit)* | |
rule token = parse | |
| ['\n' '\r'] { token lexbuf } | |
| [' ' '\t'] { token lexbuf } | |
| '=' { EQUAL } | |
| '+' { PLUS } | |
| '-' { MINUS } | |
| '*' { TIMES } | |
| '/' { DIVIDE } | |
| '(' { OPEN } | |
| ')' { CLOSE } | |
| ";;" { SEMISEMI } | |
| "->" { RIGHTARROW } | |
| digit+ { NUM(Math.BigNum.of_string(lexeme lexbuf)) } | |
| ident { lexeme lexbuf |> ident } | |
| _ { EOF } | |
and fsyacc: | |
%{ | |
open Expr | |
let applies es = | |
List.fold1_left (fun h t -> EBinOp(Apply, h, t)) es | |
%} | |
%token <string> IDENT | |
%token <Math.BigNum> NUM | |
%token EQUAL | |
%token PLUS MINUS TIMES DIVIDE POWER | |
%token OPEN CLOSE | |
%token LET REC IN | |
%token FUN RIGHTARROW | |
%token IF THEN ELSE | |
%token SEMISEMI EOF | |
%right LET REC IN | |
%right FUN RIGHTARROW | |
%right IF THEN ELSE | |
%left EQUAL | |
%left PLUS MINUS | |
%left TIMES DIVIDE | |
%right POWER | |
%left prec_uminus | |
%left prec_apply | |
%start statement | |
%type <Expr.statement option> statement | |
%% | |
fin: | |
| SEMISEMI {} | |
| EOF {} | |
; | |
rec_opt: { false } | |
| REC { true } | |
; | |
statement: | |
| fin { None } | |
| LET rec_opt IDENT EQUAL expr { Some(SLet($2, $3, $5)) } | |
| expr fin { Some(SExpr $1) } | |
; | |
simple_expr: | |
| NUM { ENum $1 } | |
| IDENT { EVar $1 } | |
| OPEN expr CLOSE { $2 } | |
; | |
simple_expr_list: | |
| simple_expr { [$1] } | |
| simple_expr simple_expr_list { $1 :: $2 } | |
; | |
expr: | |
| simple_expr { $1 } | |
| simple_expr simple_expr_list %prec prec_apply { applies ($1::$2) } | |
| expr EQUAL expr { EBinOp(Equal, $1, $3) } | |
| expr PLUS expr { $1 + $3 } | |
| expr MINUS expr { $1 - $3 } | |
| expr TIMES expr { $1 * $3 } | |
| expr DIVIDE expr { $1 / $3 } | |
| FUN IDENT RIGHTARROW expr { EFun($2, $4) } | |
| IF expr THEN expr ELSE expr { EIf($2, $4, $6) } | |
| LET rec_opt IDENT EQUAL expr IN expr { ELet($2, $3, $5, $7) } | |
; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment