From 56d36c9129292cd0dd0b5e79eea14d79a4219a94 Mon Sep 17 00:00:00 2001
From: Marcin Chrzanowski <marcin.j.chrzanowski@gmail.com>
Date: Thu, 20 Jul 2017 13:55:40 -0400
Subject: Refactor parser

---
 src/parser.js | 75 ++++++++++++++++++++++-------------------------------------
 1 file changed, 28 insertions(+), 47 deletions(-)

diff --git a/src/parser.js b/src/parser.js
index 5e9960a..fd974bc 100644
--- a/src/parser.js
+++ b/src/parser.js
@@ -6,21 +6,38 @@ let throwSyntaxError = () => {
   throw new Error('Syntax error: unexpected token')
 }
 
+let lexemeToToken = lexeme => {
+  let token = Object.create(symbols[lexeme.type])
+  token.value = lexeme.value
+  return token
+}
+
 const dieBindingPower = 30
 
 let newSymbol = (type, nud, lbp, led) => {
+  const symbol = symbols[type] || {}
   symbols[type] = {
     type,
-    nud: nud || throwSyntaxError,
-    lbp,
-    led: led || throwSyntaxError
+    nud: nud || symbol.nud || throwSyntaxError,
+    lbp: symbol.lbp || lbp,
+    led: led || symbol.led || throwSyntaxError
   }
 }
 
-let lexemeToToken = lexeme => {
-  let token = Object.create(symbols[lexeme.type])
-  token.value = lexeme.value
-  return token
+const newInfix = (symbol, lbp, options) => {
+  const type = options.type || symbol
+  const rbp = options.rbp || lbp
+  newSymbol(symbol, null, lbp, (left, parser) => {
+    return {
+      type: type,
+      left: left,
+      right: parser.expression(rbp)
+    }
+  })
+}
+
+const newDieOperation = (symbol) => {
+  newInfix(symbol, dieBindingPower, { rbp: dieBindingPower - 1 })
 }
 
 newSymbol('constant', function() {
@@ -35,59 +52,24 @@ newSymbol('(', function(parser) {
 
 newSymbol(')')
 
-const newDieOperation = (symbol, nud = null) => {
-  newSymbol(symbol, nud, dieBindingPower, (left, parser) => {
-    return {
-      type: symbol,
-      left: left,
-      right: parser.expression(dieBindingPower - 1)
-    }
-  })
-}
-
+newDieOperation('d')
 newSymbol('d', (parser) => {
   return {
     type: 'd',
     left: { type: 'constant', value: 1 },
     right: parser.expression(29)
   }
-}, 30, (left, parser) => {
-  return {
-    type: 'd',
-    left: left,
-    right: parser.expression(29)
-  }
 })
-
-newSymbol('E', null, 30, (left, parser) => {
-  return {
-    type: 'E',
-    left: left,
-    right: parser.expression(29)
-  }
-})
-
+newDieOperation('E')
 newDieOperation('K')
 
-newSymbol('+', null, 20, (left, parser) => {
-  return {
-    type: 'add',
-    left: left,
-    right: parser.expression(20)
-  }
-})
-
+newInfix('+', 20, { type: 'add' })
+newInfix('-', 20, { type: 'subtract' })
 newSymbol('-', (parser) => {
   return {
     type: 'negative',
     value: parser.expression(40)
   }
-}, 20, (left, parser) => {
-  return {
-    type: 'subtract',
-    left: left,
-    right: parser.expression(20)
-  }
 })
 
 newSymbol('end', null, -1)
@@ -132,5 +114,4 @@ const parse = expressionString => {
   return expression
 }
 
-
 exports.parse = parse
-- 
cgit v1.2.3