Home

Awesome

AL Compiler

Welcome to my project! The goal is to write a compiler without using any libraries (outside of the C++ STL). This will involve hand-rolling a lexer, parser, and assembly code generator.

Arithmetic Language is a functional language. AL is intended to be powerful enough to express complex programs. It is inspired by other functional languages, especially OCaml and Haskell.

The parser uses LL(1) parsing combined with iteration, which helps avoid some convoluted left-factored grammars. It also produces gcc-like error messages.

Game plan:

Grammar

Tokens

Productions

<Program> ::= (<TypeDecl>)* <Expr>

<Expr> ::= Ident
         | IntLit
         | FloatLit
         | BoolLit
         | <EUnitLit>
         | <ERecordLit>
         | <ELet>
         | <EIf>
         | <EFun>
         | <EFix>
         | <EFunAp>
         | <EUnaryOp>
         | <EBinaryOp>
         | <EMatch>
         | <EFieldAccess>
         | '(' <Expr> ')'
         | <Expr> ':' <EType>

<EUnitLit> ::= '(' ')'

// TODO
<ETupleLit> ::= '(' <Expr> (',' <Expr>)+ ')'

// TODO
<ERecordLit> ::= '{' Ident '=' <Expr> (',' Ident '=' <Expr>)* '}'

<EType> ::= Ident
          | <EType> '->' <EType>
          | <EType> '*' <EType>
          | '(' <EType> ')'

<ELet> ::= 'let' <Expr> '=' <Expr> 'in' <Expr>

<EIf> ::= 'if' <Expr> 'then' <Expr> 'else' <Expr>

<EFun> ::= 'fun' <Expr> '->' <Expr>

<EFix> ::= 'fix' <Expr> '->' <Expr>

<EFunAp> ::= <Expr> <Expr>

<EUnaryOp> ::= '-' <Expr>
             | '!' <Expr>

<EBinaryOp> ::= <Expr> '=' <Expr>
              | <Expr> '!=' <Expr>
              | <Expr> '<' <Expr>
              | <Expr> '>' <Expr>
              | <Expr> '<=' <Expr>
              | <Expr> '>=' <Expr>
              | <Expr> '&&' <Expr>
              | <Expr> '||' <Expr>
              | <Expr> '+' <Expr>
              | <Expr> '-' <Expr>
              | <Expr> '*' <Expr>
              | <Expr> '/' <Expr>
              | <Expr> '%' <Expr>

// TODO
<EMatch> ::= 'match' <Expr> 'with' ('|')? <MatchCase> ('|' <MatchCase>)*

<MatchCase> ::= Ident (<MatchCaseBinding>)? '->' <Expr>

<MatchCaseBinding> ::= Ident
                     | '(' Ident ')'

// TODO
<EFieldAccess> ::= <Expr> '.' Ident

<TypeDecl> ::= 'type' Ident '=' ('|')? <VariantCaseDecl> ('|' <VariantCaseDecl>)* ';'
             | 'type' Ident '=' '{' <RecordFieldDecl> (',' <RecordFieldDecl>)* '}' ';'

<VariantCaseDecl> ::= Ident
                    | Ident <EType>

<RecordFieldDecl> ::= Ident ':' <EType>

TODO: Variant constructors (FunAp on an ident and an arg), Record literals, pattern-matching, field-access, etc..