Skip to content

Commit

Permalink
parser at 70%, added ternary/logical/bitwise tests
Browse files Browse the repository at this point in the history
  • Loading branch information
mauriciopoppe committed Jul 22, 2015
1 parent e9b4178 commit 4ad96ad
Show file tree
Hide file tree
Showing 6 changed files with 347 additions and 8 deletions.
4 changes: 4 additions & 0 deletions lib/Lexer.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ var DELIMITERS = {
':': true,
'?': true,

'||': true, // logical or
'&&': true, // logical and
'xor': true, // logical xor

// relational
'==': true,
'!=': true,
Expand Down
109 changes: 104 additions & 5 deletions lib/Parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ var OperatorNode = require('./node/OperatorNode')
var SymbolNode = require('./node/SymbolNode')
var FunctionNode = require('./node/FunctionNode')
var ArrayNode = require('./node/ArrayNode')
var TernaryNode = require('./node/TernaryNode')
var AssignmentNode = require('./node/AssignmentNode')

/**
* Grammar DSL:
Expand Down Expand Up @@ -41,17 +43,17 @@ var ArrayNode = require('./node/ArrayNode')
* | shift (`!=` | `==` | `>` | '<' | '<=' |'>=') shift)
*
* shift : additive
* | additive (`>>` | `<<` | `>>>`) additive
* | additive (`>>` | `<<` | `>>>`) shift
*
* additive : multiplicative
* | multiplicative (`+` | `-`) additive
*
* multiplicative : unary
* | unary (`*` | `/` | `%` | `mod`) multiplicative
* | unary (`*` | `/` | `%`) multiplicative
* | unary symbol
*
* unary : pow
* | (`-` | `+` | `~` | `not`) unary
* | (`-` | `+` | `~`) unary
*
* pow : factorial
* | factorial (`^`) unary
Expand Down Expand Up @@ -141,7 +143,104 @@ Parser.prototype.program = function () {
}

Parser.prototype.assignment = function () {
return this.additive()
var left = this.ternary()
if (left instanceof SymbolNode && this.peek('=')) {
this.consume()
return new AssignmentNode(left.name, this.assignment())
}
return left
}

Parser.prototype.ternary = function () {
var predicate = this.logicalOR()
if (this.peek('?')) {
this.consume()
var truthy = this.ternary()
this.expect(':')
var falsy = this.ternary()
return new TernaryNode(predicate, truthy, falsy)
}
return predicate
}

Parser.prototype.logicalOR = function () {
var left = this.logicalXOR()
if (this.peek('||')) {
var op = this.consume()
var right = this.logicalOR()
return new OperatorNode(op.value, [left, right])
}
return left
}

Parser.prototype.logicalXOR = function () {
var left = this.logicalAND()
if (this.current().value === 'xor') {
var op = this.consume()
var right = this.logicalXOR()
return new OperatorNode(op.value, [left, right])
}
return left
}

Parser.prototype.logicalAND = function () {
var left = this.bitwiseOR()
if (this.peek('&&')) {
var op = this.consume()
var right = this.logicalAND()
return new OperatorNode(op.value, [left, right])
}
return left
}

Parser.prototype.bitwiseOR = function () {
var left = this.bitwiseXOR()
if (this.peek('|')) {
var op = this.consume()
var right = this.bitwiseOR()
return new OperatorNode(op.value, [left, right])
}
return left
}

Parser.prototype.bitwiseXOR = function () {
var left = this.bitwiseAND()
if (this.peek('^|')) {
var op = this.consume()
var right = this.bitwiseXOR()
return new OperatorNode(op.value, [left, right])
}
return left
}

Parser.prototype.bitwiseAND = function () {
var left = this.relational()
if (this.peek('&')) {
var op = this.consume()
var right = this.bitwiseAND()
return new OperatorNode(op.value, [left, right])
}
return left
}

Parser.prototype.relational = function () {
var left = this.shift()
if (this.peek('==', '===', '!=', '!==', '>=', '<=', '>', '<')) {
var op = this.consume()
var right = this.shift()
return new OperatorNode(op.value, [left, right])
}
return left
}

Parser.prototype.shift = function () {
var left = this.additive()
if (this.peek('>>', '<<', '>>>')) {
var op = this.consume()
var right = this.shift()
return new OperatorNode(op.value, [left, right])
}
return left
}

Parser.prototype.additive = function () {
Expand Down Expand Up @@ -179,7 +278,7 @@ Parser.prototype.multiplicative = function () {
}

Parser.prototype.unary = function () {
if (this.peek('-', '+')) {
if (this.peek('-', '+', '~')) {
var op = this.consume()
var right = this.unary()
return new OperatorNode(op.value, [right])
Expand Down
12 changes: 12 additions & 0 deletions lib/node/AssignmentNode.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
var Node = require('./Node')

function AssignmentNode (name, expr) {
this.name = name
this.expr = expr
}

AssignmentNode.prototype = Object.create(Node.prototype)

AssignmentNode.prototype.type = 'AssignmentNode'

module.exports = AssignmentNode
13 changes: 13 additions & 0 deletions lib/node/TernaryNode.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
var Node = require('./Node')

function TernaryNode (predicate, truthy, falsy) {
this.condition = predicate
this.trueExpr = truthy
this.falseExpr = falsy
}

TernaryNode.prototype = Object.create(Node.prototype)

TernaryNode.prototype.type = 'TernaryNode'

module.exports = TernaryNode
4 changes: 2 additions & 2 deletions test/lexer.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,9 @@ test('Lexer:string', function (t) {

test('Lexer:identifier', function (t) {
t.deepEqual(
doLex('mauricio'),
doLex('foo'),
[
{ value: 'mauricio', type: type.SYMBOL }
{ value: 'foo', type: type.SYMBOL }
]
)
t.deepEqual(
Expand Down
Loading

0 comments on commit 4ad96ad

Please sign in to comment.