A toy language for calculating simple expressions
Switch branches/tags
Nothing to show
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
ast
lex
parse
test_input
.travis.yml
README.md
main.go

README.md

Build Status GoDoc

calc

My toy calculator language. The lexer was inspired by the text/template/parse package from the standard library and this talk by Rob Pike: Lexical Scanning in Go The parser is a custom recursive descent parser. The parsing support was also inspired by go/parser and text/template/parse.

###TODO

  • Add more tests for parser
  • Test error cases for parser and lexer
  • Add better error messages to parser
  • Add support for val declarations
  • Add support for var declarations
  • Add if expressions
  • Add eval package and implement an interpreter
  • Add character literals
  • Add support for let statements
  • Add "=>" token to lexer
  • keep parsing expression if in a paren
  • Add support for function literals
  • Add support for function declarations
  • Add support for lists
  • Add datatypes
  • Add references and probably some for of gc
  • Add records or structs?
  • Add doc comment support to parsing
  • Add typing system(?) or go with dynamic typing
  • Add pattern matching(?)
  • Vendor dependencies(or remove them)

###Notes

  • Identifiers can be alphanumeric with an underscore '_'
  • Expressions can end with a ';' but ';' are not strictly necessary. They can be used to disambiguate certain expressions.
  • Unary Expressions cannot span multiple lines
  • Binary Expressions can span multiple lines only if line ends with operator
  • Parenthesis allows expressions to span multiple lines until the parenthesis is closed
  • Operator precedence are left binding and as follows:
Highest(5): *, /, %
       (4): +, -
       (3): ==, !=, <, >, <=, >=
       (2): &&
Lower  (1): ||
Lowest (0): anything else

e.g 4+2/3 == 4 + (2/3)
    4-5+4%a+5 == ((4 - 5) + (4%a)) + 5

##Grammar in EBNF

literal = NUMBER
        | IDENTIFIER
        | BOOL


if_expr = "if" , bool_expr , "then" , expr , "else" , expr "end"

num_expr = "+" , expr
           | "-" , expr
           | expr , "+" , expr
           | expr , "-" , expr
           | expr , "*" , expr
           | expr , "/" , expr
           | expr , "%" , expr

bool_expr = "!" , expr
            | expr , "&&" , expr
            | expr , "||" , expr
            | expr , "==" , expr
            | expr , ">" , expr
            | expr , "<" , expr
            | expr , "!=" , expr
            | expr , ">=" , expr
            | expr , "<=" , expr

tuple_expr = "(" , expr , "," , expr , { "," , expr } , ")" # n > 1

function = "fn" , "(" , ident_stmt , ")" , "=>" , expr , "end" # remove end keyword ?

block = expr , { ("\n" | ";") , expr}

let_expr = "let" , val_decl , "in" , expr , "end"

expr = literal
       | num_expr
       | bool_expr
       | if_expr
       | "(" , expr , ")"
       | tuple_expr
       | let_expr
       | block
       | function
       | func_apcl

func_apcl = (IDENTIFIER | function ) , "(" , expr , { "," , expr } , ")"

ident_stmt = IDENTIFIER

decl = val_decl
     | var_decl

val_decl = "val" , ident_stmt , "=" , expr

var_decl = "var" , ident_stmt , "=" , expr

func_decl = "def" , IDENTIFIER , "(" , IDENTIFIER , { "," , IDENTIFIER } , ")" , "=" , expr , "end"

###Planned Extensions to grammar

  • Add pattern matching to grammar
pattern = "(" , pat , "," , pat , { "," , pat } , ")" # n > 1
        | literal

val_decl = "val" , pat , "=" , expr

##Dependencies Depedencies are kept to a minimum.

# Used for testing and debugging
go get github.com/davecgh/go-spew/spew