Reorganized basically everything, making way for the compiler
This commit is contained in:
9
parser/ast.ml
Normal file
9
parser/ast.ml
Normal file
@@ -0,0 +1,9 @@
|
||||
|
||||
|
||||
type lisp_ast =
|
||||
| LInt of int
|
||||
| LDouble of float
|
||||
| LSymbol of string
|
||||
| LString of string
|
||||
| LNil
|
||||
| LCons of lisp_ast * lisp_ast
|
||||
18
parser/ast.mli
Normal file
18
parser/ast.mli
Normal file
@@ -0,0 +1,18 @@
|
||||
(** This is a simplified representation for the source code.
|
||||
Note that this is different from the data representation used
|
||||
during execution - that must naturally include things like
|
||||
functions, structs, classes, etc.
|
||||
|
||||
This is used just to represent source code in an easy to process
|
||||
manner. We translate this before actually using it.
|
||||
The interpreter directly translates to its value type, the
|
||||
compiler uses this to optimise and compile.
|
||||
**)
|
||||
|
||||
type lisp_ast =
|
||||
| LInt of int
|
||||
| LDouble of float
|
||||
| LSymbol of string
|
||||
| LString of string
|
||||
| LNil
|
||||
| LCons of lisp_ast * lisp_ast
|
||||
8
parser/dune
Normal file
8
parser/dune
Normal file
@@ -0,0 +1,8 @@
|
||||
(library
|
||||
(name parser)
|
||||
(public_name parser)
|
||||
(modules parser lex parse ast)
|
||||
)
|
||||
|
||||
(menhir (modules parse))
|
||||
(ocamllex lex)
|
||||
35
parser/lex.mll
Normal file
35
parser/lex.mll
Normal file
@@ -0,0 +1,35 @@
|
||||
{
|
||||
open Lexing
|
||||
open Parse
|
||||
exception SyntaxError of string
|
||||
|
||||
let strip_quotes s = String.sub s 1 (String.length s - 2);;
|
||||
}
|
||||
|
||||
let digit = ['0'-'9']
|
||||
let number_sign = '-' | '+'
|
||||
let int = number_sign? digit+
|
||||
let double = digit* '.' digit+ | digit+ '.' digit*
|
||||
|
||||
let white = [' ' '\t']+
|
||||
let newline = '\r' | '\n' | "\r\n"
|
||||
|
||||
let sym_char = ['a'-'z' 'A'-'Z' '!' '\\' '+' '-' '*' '/' '_' '?']
|
||||
let sym = sym_char sym_char*
|
||||
|
||||
let str = '"' [^'"']* '"'
|
||||
|
||||
rule read =
|
||||
parse
|
||||
| white { read lexbuf }
|
||||
| newline { new_line lexbuf; read lexbuf}
|
||||
| int { INT (int_of_string (Lexing.lexeme lexbuf))}
|
||||
| double { DOUBLE (float_of_string (Lexing.lexeme lexbuf))}
|
||||
| sym { SYM (Lexing.lexeme lexbuf)}
|
||||
| str { STR (strip_quotes (Lexing.lexeme lexbuf))}
|
||||
| '(' { LPAREN }
|
||||
| ')' { RPAREN }
|
||||
| '\'' { QUOTE }
|
||||
| '.' { DOT }
|
||||
| _ { raise (SyntaxError ("Unexpected char: " ^ Lexing.lexeme lexbuf))}
|
||||
| eof { EOF }
|
||||
36
parser/parse.mly
Normal file
36
parser/parse.mly
Normal file
@@ -0,0 +1,36 @@
|
||||
%{
|
||||
open Ast
|
||||
%}
|
||||
|
||||
%token <int> INT
|
||||
%token <float> DOUBLE
|
||||
%token <string> SYM
|
||||
%token <string> STR
|
||||
%token LPAREN
|
||||
%token RPAREN
|
||||
%token QUOTE
|
||||
%token DOT
|
||||
%token EOF
|
||||
|
||||
%start <lisp_ast option> prog
|
||||
%%
|
||||
|
||||
prog:
|
||||
| EOF { None }
|
||||
| e = expr { Some e }
|
||||
;
|
||||
|
||||
expr:
|
||||
| i = INT { LInt i }
|
||||
| d = DOUBLE { LDouble d}
|
||||
| s = SYM { LSymbol s }
|
||||
| s = STR { LString (String.uppercase_ascii s) }
|
||||
| LPAREN; l = lisp_list_rest { l }
|
||||
| QUOTE; e = expr { LCons (LSymbol "quote", LCons (e, LNil)) }
|
||||
;
|
||||
|
||||
lisp_list_rest:
|
||||
| RPAREN { LNil }
|
||||
| DOT; e = expr; RPAREN { e }
|
||||
| e = expr; lr = lisp_list_rest { LCons (e, lr) }
|
||||
;
|
||||
16
parser/parser.ml
Normal file
16
parser/parser.ml
Normal file
@@ -0,0 +1,16 @@
|
||||
let parse_one lb = Parse.prog (Lex.read) lb
|
||||
|
||||
let parse lb =
|
||||
let rec helper () =
|
||||
match parse_one lb with
|
||||
| None -> []
|
||||
| Some (t) -> t :: helper ()
|
||||
in
|
||||
helper ()
|
||||
|
||||
let parse_str s =
|
||||
parse (Lexing.from_string s)
|
||||
|
||||
|
||||
module Ast = Ast
|
||||
module Parse = Parse
|
||||
Reference in New Issue
Block a user