Save before fixing grouping
This commit is contained in:
parent
f0b8f181f7
commit
dbb8a5161e
@ -5,51 +5,52 @@ Operators in Pivot:
|
||||
+-------------+------------+----------------------------------+--------------------+-----------------+
|
||||
| Precedence | Operator | Description | Operands | Associativity |
|
||||
+-------------+------------+----------------------------------+--------------------+-----------------+
|
||||
| 16 | () | Grouping | internal | n/a |
|
||||
| 16 | () | Grouping | internal | n/a | grouping()
|
||||
+-------------+------------+----------------------------------+--------------------+-----------------+
|
||||
| 15 | . | Member Access | dual | Left to Right |
|
||||
| 15 | [] | Computed Member Access | before, internal | Left to Right |
|
||||
| 15 | () | Function Call | before, internal | Left to Right |
|
||||
| 15 | . | Member Access | dual | Left to Right | memberAccess()
|
||||
| 15 | [] | Computed Member Access | before, internal | Left to Right | computedMemberAccess()
|
||||
| 15 | () | Function Call | before, internal | Left to Right | functionCall()
|
||||
+-------------+------------+----------------------------------+--------------------+-----------------+
|
||||
| 14 | let | Variable Creation | after | Right to Left |
|
||||
| 14 | const | Constant Creation | after | Right to Left |
|
||||
| 14 | new | Object Creation | after | Right to Left |
|
||||
| 14 | () {} | Function Creation | internal | n/a |
|
||||
| 14 | let | Variable Creation | after | Right to Left | keywords()
|
||||
| 14 | const | Constant Creation | after | Right to Left | keywords()
|
||||
| 14 | new | Object Creation | after | Right to Left | keywords()
|
||||
| 14 | return | Function Return | after | n/a | keywords()
|
||||
| 14 | () {} | Function Creation | internal | n/a | functionCreation()
|
||||
+-------------+------------+----------------------------------+--------------------+-----------------+
|
||||
| 13 | ++ | Postfix Increment | before | Left to Right |
|
||||
| 13 | -- | Postfix Decrement | before | Left to Right |
|
||||
| 13 | ++ | Postfix Increment | before | Left to Right | postfixOperators()
|
||||
| 13 | -- | Postfix Decrement | before | Left to Right | postfixOperators()
|
||||
+-------------+------------+----------------------------------+--------------------+-----------------+
|
||||
| 12 | ! | Logical NOT | after | Right to Left |
|
||||
| 12 | - | Unary Negation | after | Right to Left |
|
||||
| 12 | ! | Logical NOT | after | Right to Left | prefixOperators()
|
||||
| 12 | - | Unary Negation | after | Right to Left | prefixOperators()
|
||||
+-------------+------------+----------------------------------+--------------------+-----------------+
|
||||
| 11 | ** | Exponentiation | dual | Right to Left |
|
||||
| 11 | ** | Exponentiation | dual | Right to Left | mathOperators(0)
|
||||
+-------------+------------+----------------------------------+--------------------+-----------------+
|
||||
| 10 | * | Multiplication | dual | Left to Right |
|
||||
| 10 | / | Division | dual | Left to Right |
|
||||
| 10 | % | Modulus | dual | Left to Right |
|
||||
| 10 | * | Multiplication | dual | Left to Right | mathOperators(1)
|
||||
| 10 | / | Division | dual | Left to Right | mathOperators(1)
|
||||
| 10 | % | Modulus | dual | Left to Right | mathOperators(1)
|
||||
+-------------+------------+----------------------------------+--------------------+-----------------+
|
||||
| 9 | + | Addition | dual | Left to Right |
|
||||
| 9 | - | Subtraction | dual | Left to Right |
|
||||
| 9 | + | Addition | dual | Left to Right | mathOperators(2)
|
||||
| 9 | - | Subtraction | dual | Left to Right | mathOperators(2)
|
||||
+-------------+------------+----------------------------------+--------------------+-----------------+
|
||||
| 7 | < | Less Than | dual | Left to Right |
|
||||
| 7 | <= | Less Than or Equal | dual | Left to Right |
|
||||
| 7 | > | Greater Than | dual | Left to Right |
|
||||
| 7 | >= | Greater Than or Equal | dual | Left to Right |
|
||||
| 7 | < | Less Than | dual | Left to Right | comparisonOperators()
|
||||
| 7 | <= | Less Than or Equal | dual | Left to Right | comparisonOperators()
|
||||
| 7 | > | Greater Than | dual | Left to Right | comparisonOperators()
|
||||
| 7 | >= | Greater Than or Equal | dual | Left to Right | comparisonOperators()
|
||||
+-------------+------------+----------------------------------+--------------------+-----------------+
|
||||
| 6 | == | Equality | dual | Left to Right |
|
||||
| 6 | != | Inequality | dual | Left to Right |
|
||||
| 6 | == | Equality | dual | Left to Right | assign()
|
||||
| 6 | != | Inequality | dual | Left to Right | assign()
|
||||
+-------------+------------+----------------------------------+--------------------+-----------------+
|
||||
| 4 | && | Logical AND | dual | Left to Right |
|
||||
| 4 | ^^ | Logical XOR | dual | Left to Right |
|
||||
| 4 | || | Logical OR | dual | Left to Right |
|
||||
| 4 | && | Logical AND | dual | Left to Right | logicOperators()
|
||||
| 4 | ^^ | Logical XOR | dual | Left to Right | logicOperators()
|
||||
| 4 | || | Logical OR | dual | Left to Right | logicOperators()
|
||||
+-------------+------------+----------------------------------+--------------------+-----------------+
|
||||
| 3 | = | Assignment | dual | Right to Left |
|
||||
| 3 | += | Add and Assign | dual | Right to Left |
|
||||
| 3 | -= | Subtract and Assign | dual | Right to Left |
|
||||
| 3 | **= | Exponentiate and Assign | dual | Right to Left |
|
||||
| 3 | *= | Multiply and Assign | dual | Right to Left |
|
||||
| 3 | /= | Divide and Assign | dual | Right to Left |
|
||||
| 3 | %= | Modulo and Assign | dual | Right to Left |
|
||||
| 3 | = | Assignment | dual | Right to Left | opAssign()
|
||||
| 3 | += | Add and Assign | dual | Right to Left | opAssign()
|
||||
| 3 | -= | Subtract and Assign | dual | Right to Left | opAssign()
|
||||
| 3 | **= | Exponentiate and Assign | dual | Right to Left | opAssign()
|
||||
| 3 | *= | Multiply and Assign | dual | Right to Left | opAssign()
|
||||
| 3 | /= | Divide and Assign | dual | Right to Left | opAssign()
|
||||
| 3 | %= | Modulo and Assign | dual | Right to Left | opAssign()
|
||||
+-------------+------------+----------------------------------+--------------------+-----------------+
|
||||
| 2 | , | Comma | none | Left to Right |
|
||||
+-------------+------------+----------------------------------+--------------------+-----------------+
|
||||
|
130
src/parser.js
130
src/parser.js
@ -22,12 +22,21 @@ function parse(tokens) {
|
||||
ast = addIndexes(ast);
|
||||
ast = addLevels(ast);
|
||||
|
||||
// Start grouping by precedence
|
||||
// Start grouping by precedence.
|
||||
|
||||
// Precedence 16.
|
||||
ast = grouping(ast);
|
||||
// Precedence 15.
|
||||
ast = memberAccess(ast);
|
||||
ast = computedMemberAccess(ast);
|
||||
ast = functionCall(ast);
|
||||
// Precedence 14.
|
||||
ast = keywords(ast);
|
||||
ast = functionCreation(ast);
|
||||
// Precedence 13.
|
||||
// Precedence 12.
|
||||
ast = postfixOperators(ast);
|
||||
ast = prefixOperators(ast);
|
||||
console.log(ast);
|
||||
|
||||
return ast;
|
||||
}
|
||||
@ -123,13 +132,15 @@ function grouping(tokens) {
|
||||
* @function memberAccess
|
||||
* @desc Combine groups of tokens by member access.
|
||||
* @param {Token[]} tokens The tokens.
|
||||
* @returns {Token[]} The grouped tokens, or the basic ast.
|
||||
* @returns {Token[]} The ast with grouped member access.
|
||||
* @private
|
||||
*/
|
||||
// TODO: Member access
|
||||
function memberAccess(ast) {
|
||||
console.log(ast);
|
||||
for (let i = 0; i < ast.length; i++) {
|
||||
if (ast[i].type == 'group')
|
||||
memberAccess(ast[i].tokens); // Recursively order the groups.
|
||||
ast[i].tokens = memberAccess(ast[i].tokens); // Recursively order the groups.
|
||||
else if (ast[i].type == 'operator' && ast[i].value == '.') { // Member access operator.
|
||||
if (typeof ast[i - 1] == 'undefined' || typeof ast[i + 1] == 'undefined')
|
||||
throw new SyntaxError('Operator requires two operands.');
|
||||
@ -143,6 +154,115 @@ function memberAccess(ast) {
|
||||
return ast;
|
||||
}
|
||||
|
||||
/**
|
||||
* @function computedMemberAccess
|
||||
* @desc Combine groups of tokens by computed member access.
|
||||
* @param {Token[]} tokens The tokens.
|
||||
* @returns {Token[]} The ast with grouped computed member access.
|
||||
* @private
|
||||
*/
|
||||
function computedMemberAccess(ast) {
|
||||
// Computed member access is Variable, Bracket Group.
|
||||
for (let i = 0; i < ast.length; i++) {
|
||||
if (ast[i].type == 'group')
|
||||
ast[i].tokens = computedMemberAccess(ast[i].tokens); // Recursively order the groups.
|
||||
else if (ast[i].type == 'name' && ast[i].subtype == 'variable') { // Member access operator.
|
||||
if (typeof ast[i + 1] == 'undefined')
|
||||
continue; // Nothing after the variable; skip this loop.
|
||||
if (ast[i + 1].type == 'group' && ast[i + 1].subtype == 'bracket') {
|
||||
ast[i + 1].tokens = computedMemberAccess(ast[i + 1].tokens); // Order the group that we care about before we mess with it.
|
||||
let op = new Operator('n/a', 'member access', [ast[i], ast[i + 1]]);
|
||||
op.index = ast[i].index;
|
||||
op.level = ast[i].level;
|
||||
ast.splice(i, 2, op);
|
||||
// Removed 2 tokens, put in 1, skip 1 token. Don't reduce the counter.
|
||||
} else continue; // Not what we need.
|
||||
}
|
||||
}
|
||||
return ast;
|
||||
}
|
||||
|
||||
/**
|
||||
* @function functionCall
|
||||
* @desc Combine groups of tokens by function calls.
|
||||
* @param {Token[]} tokens The tokens.
|
||||
* @returns {Token[]} The ast with grouped function calls.
|
||||
* @private
|
||||
*/
|
||||
function functionCall(ast) {
|
||||
// Function call is Variable, Parenthesis Group.
|
||||
for (let i = 0; i < ast.length; i++) {
|
||||
if (ast[i].type == 'group')
|
||||
ast[i].tokens = functionCall(ast[i].tokens); // Recursively order the groups.
|
||||
else if (ast[i].type == 'name' && ast[i].subtype == 'variable') { // Member access operator.
|
||||
if (typeof ast[i + 1] == 'undefined')
|
||||
continue; // Nothing after the variable; skip this loop.
|
||||
if (ast[i + 1].type == 'group' && ast[i + 1].subtype == 'parenthesis') {
|
||||
ast[i + 1].tokens = functionCall(ast[i + 1].tokens); // Order the group that we care about before we mess with it.
|
||||
let op = new Operator('function call', ast[i].value, [ast[i], ast[i + 1]]);
|
||||
op.index = ast[i].index;
|
||||
op.level = ast[i].level;
|
||||
ast.splice(i, 2, op);
|
||||
// Removed 2 tokens, put in 1, skip 1 token. Don't reduce the counter.
|
||||
} else continue; // Not what we need.
|
||||
}
|
||||
}
|
||||
return ast;
|
||||
}
|
||||
|
||||
/**
|
||||
* @function keywords
|
||||
* @desc Combine groups of tokens by keywords.
|
||||
* @param {Token[]} tokens The tokens.
|
||||
* @returns {Token[]} The ast with grouped keywords.
|
||||
* @private
|
||||
*/
|
||||
function keywords(ast) {
|
||||
for (let i = ast.length - 1; i >= 0; i--) { // Keywords are rtl associative, so loop backwards.
|
||||
if (ast[i].type == 'group')
|
||||
ast[i].tokens = keywords(ast[i].tokens); // Recursively order the groups.
|
||||
else if (ast[i].type == 'name' && ast[i].subtype == 'keyword') {
|
||||
if (typeof ast[i + 1] == 'undefined')
|
||||
throw new SyntaxError('Keyword requires one operand after it.');
|
||||
let key = new Operator('keyword', ast[i].value, [ast[i + 1]]);
|
||||
key.level = ast[i].level;
|
||||
key.index = ast[i].index;
|
||||
ast.splice(i, 2, key);
|
||||
// Looping backwards and didn't remove any items before the current one. Don't reduce the counter.
|
||||
}
|
||||
}
|
||||
return ast;
|
||||
}
|
||||
|
||||
/**
|
||||
* @function functionCreation
|
||||
* @desc Combine groups of tokens by function creation.
|
||||
* @param {Token[]} tokens The tokens.
|
||||
* @returns {Token[]} The ast with grouped function creation.
|
||||
* @private
|
||||
*/
|
||||
function functionCreation(ast) {
|
||||
// Function call is Parenthesis Group, Brace Group.
|
||||
console.log(ast);
|
||||
for (let i = 0; i < ast.length; i++) {
|
||||
if (ast[i].type == 'group')
|
||||
ast[i].tokens = functionCreation(ast[i].tokens); // Recursively order the groups.
|
||||
else if (ast[i].type == 'group' && ast[i].subtype == 'parenthesis') {
|
||||
if (typeof ast[i + 1] == 'undefined')
|
||||
continue; // Nothing after this group, ignore it.
|
||||
else if (ast[i + 1] == 'group' && ast[i].subtype == 'brace') {
|
||||
ast[i + 1].tokens = functionCreation(ast[i + 1].tokens); // Order the group that we care about before we mess with it.
|
||||
let op = new Operator('n/a', 'function creation', [ast[i], ast[i + 1]]);
|
||||
op.index = ast[i].index;
|
||||
op.level = ast[i].level;
|
||||
ast.splice(i, 2, op);
|
||||
// Removed 2 tokens, put in 1, skip 1 token. Don't reduce the counter.
|
||||
} else continue;
|
||||
}
|
||||
}
|
||||
return ast;
|
||||
}
|
||||
|
||||
/**
|
||||
* @function postfixOperators
|
||||
* @desc Recursively structures the postfix operators.
|
||||
@ -181,7 +301,7 @@ function prefixOperators(ast) {
|
||||
if (ast[i].type == 'group')
|
||||
ast[i].tokens = postfixOperators(ast[i].tokens);
|
||||
else if (ast[i].type == 'operator' && ast[i].subtype == 'prefix') { // The operand is on the right.
|
||||
if (typeof ast[i + 1] == 'undefined')
|
||||
if (typeof ast[i - 1] == 'undefined')
|
||||
throw new SyntaxError('Prefix operator requires one operand after it.');
|
||||
let op = new Operator(ast[i].subtype, ast[i].value, [ast[i + 1]]);
|
||||
op.index = ast[i].index;
|
||||
|
@ -327,7 +327,7 @@ function determineCharType(char) {
|
||||
* @private
|
||||
*/
|
||||
function determineType(str) {
|
||||
if (/let|return/.test(str))
|
||||
if (/let|const|new|return/.test(str))
|
||||
return 'keyword';
|
||||
else return 'unknown';
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user