grammar = require './grammar'
The parser takes an array of tokens generated by the lexer and creates an abstract syntax tree (AST) of sytax nodes such as Expressions, If Statements, and Assignment Statements. The actual grammar definition is defined in the grammar
module.
grammar = require './grammar'
The grammar defines a root object (a Kal File
if you inspect the grammar
module) that we use to kick off parsing and create a tree.
GrammarRoot = grammar.GrammarRoot
Grammar = grammar.Grammar
exports.Grammar = Grammar
The parse
function is the entry point for the compiler. It creates a token stream and parses it, returning the tree.
function parse(tokens, comments, options)
ts = new TokenStream(tokens, comments, options)
AST = new GrammarRoot(ts)
return AST
exports.parse = parse
The TokenStream
class allows easy navigation through the array of tokens, keeping track of line numbers and comments.
class TokenStream
method initialize(tokens, comments, options)
me.tokens = tokens
me.comments = comments
me.options = options
me.goto_token 0
Go to the next token and return it.
method next()
return me.goto_token me.index+1
Go back one token and return it.
method prev()
return me.goto_token me.index-1
Return the next token but stay at the current location in the stream.
method peek(delta_index)
me.goto_token me.index + delta_index
token = me.current
me.goto_token me.index - delta_index
return token
Go to a specific token. Generally this is not called directly; it is used by next
, prev
, and peek
.
method goto_token(index)
me.index = index
Return an EOF
token if we ran out of tokens.
if me.index > me.tokens.length - 1
me.current = {type: 'EOF', text: '', line: 0, value: ''}
else if me.index < 0
Actually error out if we try to read before the beginning of the file. This aborts compilation with a compiler error.
throw 'Parser Error: tried to read before beginning of file'
else
me.current = me.tokens[me.index]
Utility properties for the parser nodes.
me.type = me.current.type
me.text = me.current.text
me.value = me.current.value
me.line = me.current.line
return me.current