mirror of
https://github.com/hi-language/transpiler.git
synced 2026-01-13 16:18:04 +00:00
Feat: Implement operator precedence and new syntax rules
This commit is contained in:
135
src/parser.js
135
src/parser.js
@@ -1,14 +1,9 @@
|
||||
import { CstParser } from 'chevrotain';
|
||||
import {
|
||||
allTokens,
|
||||
Identifier, Number, String,
|
||||
LBrace, RBrace, LParen, RParen,
|
||||
Dot, Plus, Comma, Colon, Eq
|
||||
} from './lexer.js';
|
||||
import * as T from './lexer.js';
|
||||
|
||||
class HiParser extends CstParser {
|
||||
constructor() {
|
||||
super(allTokens);
|
||||
super(T.allTokens);
|
||||
|
||||
const $ = this;
|
||||
|
||||
@@ -19,86 +14,136 @@ class HiParser extends CstParser {
|
||||
$.OR([
|
||||
{ ALT: () => $.SUBRULE($.declaration) },
|
||||
{ ALT: () => $.SUBRULE($.assignment) },
|
||||
{ ALT: () => $.SUBRULE($.returnStatement) },
|
||||
{ ALT: () => $.SUBRULE($.expressionStatement) },
|
||||
]);
|
||||
});
|
||||
|
||||
$.RULE('expressionStatement', () => $.SUBRULE($.expression));
|
||||
|
||||
$.RULE('returnStatement', () => {
|
||||
$.CONSUME(T.Caret);
|
||||
$.OPTION(() => $.SUBRULE($.expression));
|
||||
});
|
||||
|
||||
$.RULE('declaration', () => {
|
||||
$.CONSUME(Identifier);
|
||||
$.CONSUME(Colon);
|
||||
$.CONSUME(T.Identifier);
|
||||
$.CONSUME(T.Colon);
|
||||
$.SUBRULE($.expression);
|
||||
});
|
||||
|
||||
$.RULE('assignment', () => {
|
||||
$.CONSUME(Identifier);
|
||||
$.CONSUME(Eq);
|
||||
// Note: This only allows simple identifiers for now, not member expressions.
|
||||
$.CONSUME(T.Identifier);
|
||||
$.CONSUME(T.Eq);
|
||||
$.SUBRULE($.expression);
|
||||
});
|
||||
|
||||
$.RULE('expression', () => $.SUBRULE($.additiveExpression));
|
||||
$.RULE('expression', () => $.SUBRULE($.conditionalExpression));
|
||||
|
||||
$.RULE('additiveExpression', () => {
|
||||
$.SUBRULE($.callExpression, { LABEL: 'left' });
|
||||
$.MANY(() => {
|
||||
$.CONSUME(Plus);
|
||||
$.SUBRULE2($.callExpression, { LABEL: 'right' });
|
||||
});
|
||||
});
|
||||
|
||||
$.RULE('callExpression', () => {
|
||||
$.SUBRULE($.memberExpression);
|
||||
$.RULE('conditionalExpression', () => {
|
||||
$.SUBRULE($.equalityExpression, { LABEL: 'condition' });
|
||||
$.OPTION(() => {
|
||||
$.CONSUME(LParen);
|
||||
$.OPTION2(() => $.SUBRULE($.argumentList));
|
||||
$.CONSUME(RParen);
|
||||
$.CONSUME(T.Question);
|
||||
$.SUBRULE2($.expression, { LABEL: 'consequent' });
|
||||
$.OPTION2(() => {
|
||||
$.CONSUME(T.Colon);
|
||||
$.SUBRULE3($.expression, { LABEL: 'alternate' });
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
$.RULE('argumentList', () => {
|
||||
$.SUBRULE($.expression);
|
||||
const buildBinaryExpressionRule = (name, higherPrecRule, operators) => {
|
||||
$.RULE(name, () => {
|
||||
$.SUBRULE(higherPrecRule, { LABEL: 'left' });
|
||||
$.MANY(() => {
|
||||
$.CONSUME($.OR(operators));
|
||||
$.SUBRULE2(higherPrecRule, { LABEL: 'right' });
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
buildBinaryExpressionRule('equalityExpression', $.additiveExpression, [
|
||||
{ ALT: () => T.EqEq }
|
||||
]);
|
||||
|
||||
buildBinaryExpressionRule('additiveExpression', $.multiplicativeExpression, [
|
||||
{ ALT: () => T.Plus }, { ALT: () => T.Minus }
|
||||
]);
|
||||
|
||||
buildBinaryExpressionRule('multiplicativeExpression', $.callExpression, [
|
||||
{ ALT: () => T.Star }, { ALT: () => T.Slash }
|
||||
]);
|
||||
|
||||
$.RULE('callExpression', () => {
|
||||
$.SUBRULE($.memberExpression, { LABEL: 'callee' });
|
||||
$.MANY(() => {
|
||||
$.CONSUME(Comma);
|
||||
$.SUBRULE2($.expression);
|
||||
$.CONSUME(T.LParen);
|
||||
$.OPTION(() => $.SUBRULE($.argumentList));
|
||||
$.CONSUME(T.RParen);
|
||||
});
|
||||
});
|
||||
|
||||
$.RULE('argumentList', () => $.SEPERATED_LIST($.expression, T.Comma));
|
||||
|
||||
$.RULE('memberExpression', () => {
|
||||
$.SUBRULE($.primary);
|
||||
$.SUBRULE($.primary, { LABEL: 'object' });
|
||||
$.MANY(() => {
|
||||
$.CONSUME(Dot);
|
||||
$.CONSUME(Identifier);
|
||||
$.OR([
|
||||
{ ALT: () => { $.CONSUME(T.Dot); $.CONSUME(T.Identifier); }},
|
||||
{ ALT: () => { $.CONSUME(T.LBracket); $.SUBRULE($.expression); $.CONSUME(T.RBracket); }}
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
$.RULE('primary', () => {
|
||||
$.OR([
|
||||
{ ALT: () => $.SUBRULE($.literal) },
|
||||
{ ALT: () => $.CONSUME(Identifier) },
|
||||
{ ALT: () => $.CONSUME(T.Identifier) },
|
||||
{ ALT: () => $.CONSUME(T.At) },
|
||||
{ ALT: () => $.SUBRULE($.arrowExpression) },
|
||||
{ ALT: () => $.SUBRULE($.block) },
|
||||
{ ALT: () => $.SUBRULE($.arrayLiteral) },
|
||||
{ ALT: () => {
|
||||
$.CONSUME(LParen);
|
||||
$.CONSUME(T.LParen);
|
||||
$.SUBRULE($.expression);
|
||||
$.CONSUME(RParen);
|
||||
$.CONSUME(T.RParen);
|
||||
}}
|
||||
]);
|
||||
});
|
||||
|
||||
$.RULE('literal', () => $.OR([{ ALT: () => $.CONSUME(Number) }, { ALT: () => $.CONSUME(String) }]));
|
||||
$.RULE('literal', () => $.OR([
|
||||
{ ALT: () => $.CONSUME(T.Number) },
|
||||
{ ALT: () => $.CONSUME(T.String) },
|
||||
{ ALT: () => $.CONSUME(T.Null) }
|
||||
]));
|
||||
|
||||
$.RULE('arrowExpression', () => {
|
||||
$.SUBRULE($.parameterList);
|
||||
$.CONSUME(T.Arrow);
|
||||
$.OR([
|
||||
{ ALT: () => $.SUBRULE($.block) },
|
||||
{ ALT: () => $.SUBRULE($.expression) }
|
||||
]);
|
||||
});
|
||||
|
||||
$.RULE('arrayLiteral', () => {
|
||||
$.CONSUME(T.LBracket);
|
||||
$.OPTION(() => $.SEPERATED_LIST($.expression, T.Comma));
|
||||
$.CONSUME(T.RBracket);
|
||||
});
|
||||
|
||||
$.RULE('block', () => {
|
||||
$.CONSUME(LBrace);
|
||||
$.OPTION(() => $.SUBRULE($.keyValuePairs));
|
||||
$.CONSUME(RBrace);
|
||||
$.OPTION(() => $.SUBRULE($.parameterList));
|
||||
$.CONSUME(T.LBrace);
|
||||
$.SUBRULE($.statements);
|
||||
$.CONSUME(T.RBrace);
|
||||
});
|
||||
|
||||
$.RULE('keyValuePairs', () => $.AT_LEAST_ONE(() => $.SUBRULE($.keyValuePair)));
|
||||
|
||||
$.RULE('keyValuePair', () => {
|
||||
$.CONSUME(Identifier);
|
||||
$.CONSUME(Colon);
|
||||
$.SUBRULE($.expression);
|
||||
$.RULE('parameterList', () => {
|
||||
$.CONSUME(T.LParen);
|
||||
$.OPTION(() => $.SEPERATED_LIST(T.Identifier, T.Comma));
|
||||
$.CONSUME(T.RParen);
|
||||
});
|
||||
|
||||
this.performSelfAnalysis();
|
||||
|
||||
Reference in New Issue
Block a user