Skip to content

Instantly share code, notes, and snippets.

@papersail
Created April 8, 2011 01:39
Show Gist options
  • Save papersail/909140 to your computer and use it in GitHub Desktop.
Save papersail/909140 to your computer and use it in GitHub Desktop.
mfcalc (translated from Ocaml to F#)
{
module Lexer
open System
open Parser
open Microsoft.FSharp.Text.Lexing
let lexeme = LexBuffer<_>.LexemeString
let func_table = [
"sin", sin;
"cos", cos;
"tan", tan;
"asin", asin;
"acos", acos;
"atan", atan;
"log", log;
"exp", exp;
"sqrt", sqrt;
]
let functions = Map.ofList func_table
let ident lexbuf tokenText =
if Map.containsKey tokenText functions then
let f = Map.find tokenText functions
FNCT f
else
VAR tokenText
}
let digit = ['0'-'9']+
let alpha = ['a'-'z' 'A'-'Z']
let ident = alpha+ (alpha | digit)*
let floatNum = digit ('.' digit)?
let newline = '\n'
rule token = parse
| [' ' '\t'] { token lexbuf }
| floatNum { NUM (Double.Parse(lexeme lexbuf)) }
| newline { NEWLINE }
| '+' { PLUS }
| '-' { MINUS }
| '*' { MULTIPLY }
| '/' { DIVIDE }
| '^' { CARET }
| '(' { LPAREN }
| ')' { RPAREN }
| '=' { EQ}
| ident { ident lexbuf (lexeme lexbuf) }
| _ { token lexbuf }
| eof { EOF }
open System
open Parser
open Lexer
let main () =
let lexbuf = Lexing.LexBuffer<_>.FromTextReader Console.In
while not lexbuf.IsPastEndOfStream do
Parser.input Lexer.token lexbuf
main ()
%{
open System
let var_table = Map.empty
%}
%token LPAREN RPAREN EQ
%token <float> NUM
%token PLUS MINUS MULTIPLY DIVIDE CARET
%token <string> VAR
%token <float->float> FNCT
%token NEWLINE EOF
%left PLUST MINUS
%left MULTIPLY DIVIDE
%left NEG
%right CARET
%start input
%type <unit> input
%%
input: { }
| input line { }
line: NEWLINE {}
| exp NEWLINE { printf "\t%.10g\n" $1
Console.Out.Flush() }
exp: NUM { $1 }
| VAR { if Map.containsKey $1 var_table then
Map.find $1 var_table
else
0.0
}
| VAR EQ exp { Map.add $1 $3 var_table |> ignore; $3 }
| FNCT LPAREN exp RPAREN { $1 $3 }
| exp PLUS exp { $1 + $3 }
| exp MINUS exp { $1 - $3 }
| exp MULTIPLY exp { $1 * $3 }
| exp DIVIDE exp { $1 / $3 }
| exp CARET exp { $1 ** $3 }
| MINUS exp %prec NEG { - $2 }
| LPAREN exp RPAREN { $2 }
%%
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment