Creative Commons Licence This work is licensed under a Creative Commons
Attribution-ShareAlike 4.0 International License

How to write a programming language

Part 2: The Parser

Andy Balaam
artificialworlds.net/blog

Contents

Recap

Recap - Lexing

foo = "bar";

becomes:

("symbol", "foo") ("=" , "" ) ("string", "bar") (";" , "" )

Recap - Lexing

print( x + 2 );

becomes:

("symbol" , "print") ("(" , "" ) ("symbol" , "x" ) ("operator", "+" ) ("number" , "2" ) (")" , "" ) (";" , "" )

Parsing

Parsing

x = 3 + 4;

becomes:

Assignment: Symbol: x Value: Operation: Type: + Arguments: 3 4

Parsing

print( x + 2 );

becomes:

FunctionCall: Function: print Arguments: Operation: Type: + Arguments: x 2

Parsing

print( x + 2 );

becomes:

("call", ("symbol", "print"), [ ("operation", "+", ("symbol", "x"), ("number", "2") ) ] )

More about Cell

Cell has four expression types:

More about Cell

The coolest thing about Cell is:

More at: github.com/andybalaam/cell

More about Cell

if( is_even( 2 ), { print "Even!"; }, { print "Odd."; } );

More at: github.com/andybalaam/cell

Cell's parser

def parse(tokens): parser = Parser(tokens, ";") while parser.tokens.next is not None: p = parser.next_expr(None) if p is not None: yield p parser.tokens.move_next()

Cell's parser

class Parser: def __init__(self, tokens, stop_at): self.tokens = tokens self.stop_at = stop_at

Cell's parser

def next_expr(self, prev): self.fail_if_at_end(";") typ, value = self.tokens.next if typ in self.stop_at: return prev self.tokens.move_next() # ...

Cell's parser

def next_expr(self, prev): # ... if prev is None and typ in (# ... elif typ == "operation": # ... elif typ == "(": # ... elif typ == "{": # ... elif typ == "=": # ... else: # ...

Cell's parser

def next_expr(self, prev): # ... if prev is None and typ in ( "number", "string", "symbol"): return self.next_expr((typ, value)) elif typ == "operation": # ... elif typ == "(": # ... elif typ == "{": # ... elif typ == "=": # ... else: # ...

Cell's parser

def next_expr(self, prev): # ... if prev is None and typ in (... elif typ == "operation": nxt = self.next_expr(None) return self.next_expr( ("operation", value, prev, nxt)) elif typ == "(": # ... elif typ == "{": # ... elif typ == "=": # ... else: # ...

Cell's parser

def next_expr(self, prev): # ... if prev is None and typ in (... elif typ == "operation": # ... elif typ == "(": args = self.multi_exprs(",", ")") return self.next_expr(("call", prev, args)) elif typ == "{": # ... elif typ == "=": # ... else: # ...

Cell's parser

def multi_exprs(self, sep, end): ret = [] self.fail_if_at_end(end) typ = self.tokens.next[0] if typ == end: self.tokens.move_next() else: # ... return ret

Cell's parser

def multi_exprs(self, sep, end): # ... else: arg_parser = Parser(self.tokens, (sep, end)) while typ != end: p = arg_parser.next_expr(None) if p is not None: ret.append(p) typ = self.tokens.next[0] self.tokens.move_next() self.fail_if_at_end(end) return ret

Cell's parser

def next_expr(self, prev): # ... elif typ == "(": # ... elif typ == "{": params = self.parameters_list() body = self.multi_exprs(";", "}") return self.next_expr(("function", params, body)) elif typ == "=": # ... else: # ...

Cell's parser

def next_expr(self, prev): # ... elif typ == "(": # ... elif typ == "{": # ... elif typ == "=": if prev[0] != "symbol": raise Exception(...) nxt = self.next_expr(None) return self.next_expr(("assignment", prev, nxt)) else: # ...

Cell's parser

def next_expr(self, prev): # ... elif typ == "(": # ... elif typ == "{": # ... elif typ == "=": # ... else: raise Exception("Unexpected token: " ...

Discussion

Donate

Donate! patreon.com/andybalaam

Play

Play! artificialworlds.net/rabbit-escape

More info

Videos youtube.com/user/ajbalaam
Twitter @andybalaam
Blog artificialworlds.net/blog
Projects artificialworlds.net
GitHub github.com/andybalaam