mirror of
https://github.com/hi-language/transpiler.git
synced 2026-01-14 00:28:05 +00:00
154 lines
5.0 KiB
JavaScript
154 lines
5.0 KiB
JavaScript
import { CstParser } from 'chevrotain';
|
|
import * as T from './lexer.js';
|
|
|
|
class HiParser extends CstParser {
|
|
constructor() {
|
|
super(T.allTokens);
|
|
|
|
const $ = this;
|
|
|
|
$.RULE('program', () => $.SUBRULE($.statements));
|
|
$.RULE('statements', () => $.MANY(() => $.SUBRULE($.statement)));
|
|
|
|
$.RULE('statement', () => {
|
|
$.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(T.Identifier);
|
|
$.CONSUME(T.Colon);
|
|
$.SUBRULE($.expression);
|
|
});
|
|
|
|
$.RULE('assignment', () => {
|
|
// Note: This only allows simple identifiers for now, not member expressions.
|
|
$.CONSUME(T.Identifier);
|
|
$.CONSUME(T.Eq);
|
|
$.SUBRULE($.expression);
|
|
});
|
|
|
|
$.RULE('expression', () => $.SUBRULE($.conditionalExpression));
|
|
|
|
$.RULE('conditionalExpression', () => {
|
|
$.SUBRULE($.equalityExpression, { LABEL: 'condition' });
|
|
$.OPTION(() => {
|
|
$.CONSUME(T.Question);
|
|
$.SUBRULE2($.expression, { LABEL: 'consequent' });
|
|
$.OPTION2(() => {
|
|
$.CONSUME(T.Colon);
|
|
$.SUBRULE3($.expression, { LABEL: 'alternate' });
|
|
});
|
|
});
|
|
});
|
|
|
|
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(T.LParen);
|
|
$.OPTION(() => $.SUBRULE($.argumentList));
|
|
$.CONSUME(T.RParen);
|
|
});
|
|
});
|
|
|
|
$.RULE('argumentList', () => $.SEPERATED_LIST($.expression, T.Comma));
|
|
|
|
$.RULE('memberExpression', () => {
|
|
$.SUBRULE($.primary, { LABEL: 'object' });
|
|
$.MANY(() => {
|
|
$.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(T.Identifier) },
|
|
{ ALT: () => $.CONSUME(T.At) },
|
|
{ ALT: () => $.SUBRULE($.arrowExpression) },
|
|
{ ALT: () => $.SUBRULE($.block) },
|
|
{ ALT: () => $.SUBRULE($.arrayLiteral) },
|
|
{ ALT: () => {
|
|
$.CONSUME(T.LParen);
|
|
$.SUBRULE($.expression);
|
|
$.CONSUME(T.RParen);
|
|
}}
|
|
]);
|
|
});
|
|
|
|
$.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', () => {
|
|
$.OPTION(() => $.SUBRULE($.parameterList));
|
|
$.CONSUME(T.LBrace);
|
|
$.SUBRULE($.statements);
|
|
$.CONSUME(T.RBrace);
|
|
});
|
|
|
|
$.RULE('parameterList', () => {
|
|
$.CONSUME(T.LParen);
|
|
$.OPTION(() => $.SEPERATED_LIST(T.Identifier, T.Comma));
|
|
$.CONSUME(T.RParen);
|
|
});
|
|
|
|
this.performSelfAnalysis();
|
|
}
|
|
}
|
|
|
|
export const parser = new HiParser();
|