Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- namespace Components.Aphid;
- token AphidTokenType;
- base AphidExpression;
- node AphidNodeType;
- parser AphidParser;
- ////////////////////////////////////////////////////////////////
- // Types
- ////////////////////////////////////////////////////////////////
- BinaryOperatorExpression = { LeftOperand, AphidTokenType Operator, RightOperand };
- UnaryOperatorExpression = { AphidTokenType Operator, Operand, opt bool IsPostfix };
- CallExpression = { FunctionExpression, opt list Args };
- TernaryOperatorExpression = { AphidTokenType Operator, FirstOperand, SecondOperand, ThirdOperand };
- ArrayAccessExpression = { ArrayExpression, KeyExpression };
- IdentifierExpression = { string Identifier, opt list IdentifierExpression Attributes };
- IfExpression = { Condition, list Body, list ElseBody };
- DynamicMemberExpression = { foo foo };
- ExtendExpression = { string ExtendType, ObjectExpression Object };
- ForEachExpression = { foo foo };
- ForExpression = { foo foo };
- WhileExpression = { foo foo };
- DoWhileExpression = { foo foo };
- LoadScriptExpression = { FileExpression };
- LoadLibraryExpression = { LibraryExpression };
- TryExpression = { list TryBody, IdentifierExpression CatchArg, list CatchBody, list FinallyBody };
- SwitchExpression = { foo foo };
- SwitchCase = { foo foo };
- StringExpression = { foo foo };
- ObjectExpression = { foo };
- ArrayExpression = { foo };
- FunctionExpression = { foo };
- PartialFunctionExpression = { foo };
- PatternMatchingExpression = { foo };
- PatternExpression = { foo };
- NumberExpression = { decimal Value, };
- ////////////////////////////////////////////////////////////////
- // Macros
- ////////////////////////////////////////////////////////////////
- Delim = macro(@(_left, _value, _right) {
- Match(_left);
- _value;
- Match(_right);
- });
- Parens = macro(@(_value) { Delim(LeftParenthesis, _value, RightParenthesis); });
- Prefix = macro(@(_token, _value) {
- Match(_token);
- _value;
- });
- TakeToken = macro(@(_var) {
- _var = TokenType;
- NextToken;
- });
- SkipThen = macro(@(_retVal) {
- @() {
- NextToken;
- ret _retVal;
- };
- });
- ThenSkip = macro(@(_retVal) {
- @() {
- exp = _retVal;
- NextToken;
- ret exp;
- };
- });
- ParseBinOpExp = macro(@(_parse, _ops) {
- @() {
- operand = _parse();
- while (_ops) {
- TakeToken(op);
- operand = BinaryOperatorExpression(operand, op, _parse());
- }
- ret operand;
- };
- });
- ////////////////////////////////////////////////////////////////
- // Functions
- ////////////////////////////////////////////////////////////////
- root list Parse = @() {
- expressionSequence;
- NextToken;
- while (!None) expressionSequence += ParseStatement();
- ret expressionSequence;
- };
- ParseStatement = _ParseStatement(true);
- ParseSingleStatement = _ParseStatement(false);
- _ParseStatement = macro(@(_requireEos) {
- @() {
- exp;
- // Todo add support for $ op
- switch (TokenType) {
- ifKeyword: exp ParseIfExpression;
- forKeyword: exp ParseForExpression;
- whileKeyword: exp ParseWhileExpression;
- doKeyword: {
- exp ParseDoWhileExpression;
- MatchEos(_requireEos);
- }
- extendKeyword: exp ParseExtendExpression;
- tryKeyword: exp ParseTryExpression;
- switchKeyword: exp ParseSwitchExpression;
- default: {
- exp ParseExpression;
- MatchEos(_requireEos);
- }
- }
- ret exp;
- };
- });
- MatchEos = macro(@(_requireEos) { if (_requireEos) EndOfStatement; });
- ParseExpression = @() ParseAssignmentExpression();
- ParseAssignmentExpression = ParseBinOpExp(
- ParsePipelineExpression,
- AssignmentOperator |
- PlusEqualOperator |
- MinusEqualOperator |
- MultiplicationEqualOperator |
- DivisionEqualOperator |
- ModulusEqualOperator |
- BinaryAndEqualOperator |
- OrEqualOperator |
- XorEqualOperator |
- ShiftLeftEqualOperator |
- ShiftRightEqualOperator);
- ParsePipelineExpression = ParseBinOpExp(ParseQueryExpression, PipelineOperator);
- ParseQueryExpression = @() {
- exp ParseRangeExpression;
- inQuery = true;
- do {
- switch (TokenType) {
- AggregateOperator,
- AnyOperator,
- SelectManyOperator,
- SelectOperator,
- WhereOperator: {
- TakeToken(t);
- exp = BinaryOperatorExpression(exp, t, ParseRangeExpression());
- }
- DistinctOperator: {
- exp = UnaryOperatorExpression(TokenType, exp);
- NextToken;
- }
- default: inQuery = false;
- }
- } while(inQuery);
- ret exp;
- };
- ParseRangeExpression = ParseBinOpExp(ParseConditionalExpression, RangeOperator);
- ParseConditionalExpression = @() {
- exp ParseLogicalExpression;
- if (ConditionalOperator) {
- NextToken;
- trueExpression ParseExpression;
- ColonOperator;
- falseExpression ParseExpression;
- ret TernaryOperatorExpression(
- ConditionalOperator,
- exp,
- trueExpression,
- falseExpression);
- } else {
- ret exp;
- }
- };
- ParseLogicalExpression = ParseBinOpExp(ParseComparisonExpression, AndOperator | OrOperator);
- ParseComparisonExpression = ParseBinOpExp(
- ParsePostfixUnaryOperationExpression,
- EqualityOperator |
- NotEqualOperator |
- LessThanOperator |
- LessThanOrEqualOperator |
- GreaterThanOperator |
- GreaterThanOrEqualOperator);
- ParsePostfixUnaryOperationExpression = @() {
- term = ParseBinaryOrExpression();
- switch (TokenType) {
- IncrementOperator, DecrementOperator: {
- TakeToken(op);
- ret UnaryOperatorExpression(op, term, true);
- }
- default: ret term;
- }
- };
- ParseBinaryOrExpression = ParseBinOpExp(ParseXorExpression, BinaryOrOperator);
- ParseXorExpression = ParseBinOpExp(ParseBinaryAndExpression, XorOperator);
- ParseBinaryAndExpression = ParseBinOpExp(ParseShiftExpression, BinaryAndOperator);
- ParseShiftExpression = ParseBinOpExp(ParseAdditionExpression, ShiftLeft | ShiftRight);
- ParseAdditionExpression = ParseBinOpExp(ParseTermExpression, AdditionOperator | MinusOperator);
- ParseTermExpression = ParseBinOpExp(
- ParsePrefixUnaryOperatorExpression,
- MultiplicationOperator | DivisionOperator | ModulusOperator);
- ParsePrefixUnaryOperatorExpression = @() {
- switch (TokenType) {
- AdditionOperator,
- MinusOperator,
- NotOperator,
- IncrementOperator,
- DecrementOperator,
- MultiplicationOperator,
- ComplementOperator: {
- TakeToken(t);
- ret UnaryOperatorExpression(t, ParseArrayAccessExpression());
- }
- default: ret ParseArrayAccessExpression();
- }
- };
- ParseArrayAccessExpression = @() {
- exp ParseCallExpression;
- while (LeftBracket) {
- NextToken;
- key ParseExpression;
- RightBracket;
- exp = ArrayAccessExpression(exp, key);
- }
- ret exp;
- };
- ParseCall = macro(@(_parseFunc) {
- @() {
- function = _parseFunc();
- while (LeftParenthesis) {
- NextToken;
- if (RightParenthesis) {
- NextToken;
- function = CallExpression(function);
- } else {
- args ParseTuple;
- RightParenthesis;
- function = CallExpression(function, args);
- }
- }
- ret function;
- };
- });
- ParseCallBody = macro(@(_func) {
- while (LeftParenthesis) {
- NextToken;
- if (RightParenthesis) {
- NextToken;
- _func = CallExpression(_func);
- } else {
- args = ParseTuple();
- RightParenthesis;
- _func = CallExpression(_func, args);
- }
- }
- });
- ParseCallExpression = ParseCall(ParseMemberExpression);
- ParseMemberExpression = @() {
- factor ParseFactorCallExpression;
- while (MemberOperator) {
- NextToken;
- exp;
- switch (TokenType) {
- Identifier: {
- exp = IdentifierExpression(Lexeme);
- NextToken;
- }
- String: exp ParseStringExpression;
- LeftBrace: {
- NextToken;
- exp = DynamicMemberExpression(ParseExpression());
- RightBrace;
- }
- default: {
- // Todo: exception handling
- //throw new AphidParserException(_currentToken);
- }
- }
- factor = BinaryOperatorExpression(factor, MemberOperator, exp);
- ParseCallBody(factor);
- if (definedKeyword) {
- NextToken;
- ret UnaryOperatorExpression(definedKeyword, factor, true);
- }
- }
- ret factor;
- };
- ParseFactorCallExpression = ParseCall(ParseFactorExpression);
- ParseStringExpression = Lexeme |> StringExpression |> ThenSkip;
- ParseFactorExpression = @() { };
- IdentifierExpression ParseIdentifierExpression = @() {
- exp = IdentifierExpression(Lexeme);
- NextToken;
- if (Identifier) {
- id = exp;
- // Add support for [] instead of 'list IdentifierExpression', infer type
- attrs = list IdentifierExpression;
- do {
- attrs += id;
- id = IdentifierExpression(Lexeme);
- NextToken;
- } while (Identifier);
- exp = IdentifierExpression(id.Identifier, attrs);
- }
- ret exp;
- };
- ParseUnaryExpression = @() {
- TakeToken(t);
- ret UnaryOperatorExpression(t, ParseExpression());
- };
- ParseCondition = @() {
- Parens(condition ParseExpression);
- ret condition;
- };
- ParseIfExpression = @() {
- NextToken;
- condition ParseCondition;
- body ParseBlock;
- list elseBody;
- if (elseKeyword)
- {
- NextToken;
- elseBody ParseBlock;
- }
- ret IfExpression(condition, body, elseBody);
- };
- _ParseBlock = macro(@(_parseStatement) {
- @() {
- statements;
- if (LeftBrace) {
- NextToken;
- while (!RightBrace) statements += ParseStatement();
- NextToken;
- } else {
- statements += _parseStatement();
- }
- ret statements;
- };
- });
- list ParseBlock = _ParseBlock(ParseStatement);
- list ParseSingleBlock = _ParseBlock(ParseSingleStatement);
- // Todo: infer return type and cast if necessary.
- // Todo: Extend expression should probably accept IdExp to support attributes
- ParseExtendExpression = SkipThen(
- ExtendExpression(ParseIdentifierExpression().Identifier, ParseObjectExpression()));
- // Todo: support empty objects
- ParseForExpression = @() {
- NextToken;
- LeftParenthesis;
- initOrElement ParseExpression;
- if (inKeyword) {
- NextToken;
- collection ParseExpression;
- RightParenthesis;
- body ParseBlock;
- ret ForEachExpression(collection, initOrElement, body);
- } else {
- EndOfStatement;
- condition ParseExpression;
- EndOfStatement;
- afterthought ParseExpression;
- RightParenthesis;
- body ParseBlock;
- ret ForExpression(initOrElement, condition, afterthought, body);
- }
- };
- ParseWhileExpression = SkipThen(WhileExpression(ParseCondition(), ParseBlock()));
- ParseDoWhileExpression = @() {
- NextToken;
- body ParseBlock;
- Prefix(whileKeyword, Parens(condition ParseExpression));
- ret DoWhileExpression(condition, body);
- };
- list ParseTuple = @() {
- tuple;
- while (true) {
- tuple += ParseExpression();
- if (Comma) NextToken;
- else ret tuple;
- }
- };
- ParseLoadScriptExpression = SkipThen(LoadScriptExpression(ParseExpression()));
- ParseLoadLibraryExpression = SkipThen(LoadLibraryExpression(ParseExpression()));
- // Todo: fix now that var decls work
- ParseTryExpression = @() {
- NextToken;
- tryBody ParseBlock;
- IdentifierExpression catchArg;
- list catchBody;
- list finallyBody;
- switch (TokenType) {
- catchKeyword: {
- NextToken;
- Parens(catchArg ParseIdentifierExpression);
- catchBody ParseBlock;
- if (finallyKeyword) {
- NextToken;
- finallyBody ParseBlock;
- }
- }
- finallyKeyword: {
- NextToken;
- finallyBody ParseBlock;
- }
- default: {
- ret null;
- // Todo: add parser throw
- }
- }
- ret TryExpression(tryBody, catchArg, catchBody, finallyBody);
- };
- ParseSwitchExpression = @() {
- NextToken;
- Parens(exp ParseExpression);
- LeftBrace;
- cases = list SwitchCase;
- list defaultCase;
- while (!RightBrace) {
- if (!defaultKeyword) {
- caseTuple ParseTuple;
- ColonOperator;
- block ParseBlock;
- cases += SwitchCase(caseTuple, block);
- } else {
- NextToken;
- ColonOperator;
- defaultCase ParseBlock;
- }
- }
- NextToken;
- ret SwitchExpression(exp, cases, defaultCase);
- };
- ParseObjectExpression = @() { };
- ObjectExpression ParseObjectExpression = @() {
- NextToken;
- inNode = true;
- childNodes = list BinaryOperatorExpression;
- while (inNode) {
- switch (TokenType) {
- Identifier: {
- childNodes += ParseKeyValuePairExpression();
- switch (TokenType) {
- Comma: NextToken;
- RightBrace: {
- NextToken;
- inNode = false;
- }
- default: {
- // Todo: error
- }
- }
- }
- RightBrace: {
- NextToken;
- inNode = false;
- }
- default: {
- // Todo: error
- }
- }
- }
- ret ObjectExpression(childNodes);
- };
- ParseArrayExpression = @() {
- NextToken;
- inNode = true;
- childNodes = list AphidExpression;
- if (!RightBracket) {
- while (inNode) {
- childNodes += ParseExpression();
- switch (TokenType) {
- Comma: {
- NextToken;
- if (RightBracket) {
- NextToken;
- inNode = false;
- }
- }
- RightBracket: {
- NextToken;
- inNode = false;
- }
- default: {
- // Todo: error
- }
- }
- }
- } else {
- NextToken;
- }
- ret ArrayExpression(childNodes);
- };
- BinaryOperatorExpression ParseKeyValuePairExpression = @() {
- id ParseIdentifierExpression;
- exp;
- if (ColonOperator || AssignmentOperator) {
- NextToken;
- exp ParseExpression;
- } else {
- exp = id;
- }
- ret BinaryOperatorExpression(id, ColonOperator, exp);
- };
- ParseNumberExpression = @(){
- exp = NumberExpression(decimal.Parse(Lexeme));
- NextToken;
- ret exp;
- };
- ParseFunctionExpression = @() {
- exp;
- body;
- args;
- argExp;
- NextToken;
- switch (TokenType) {
- LeftParenthesis: {
- NextToken;
- if (!RightParenthesis) {
- while (true) {
- if (Identifier) {
- id ParseIdentifierExpression;
- argExp = id;
- if (AssignmentOperator) {
- TakeToken(op);
- argExp = BinaryOperatorExpression(id, op, ParseExpression());
- }
- args += argExp;
- if (Comma) NextToken;
- else break;
- } else {
- // Todo: error
- }
- }
- }
- RightParenthesis;
- isSingleLine = TokenType != LeftBrace;
- block = ParseSingleBlock();
- if (isSingleLine && UseImplicitReturns) {
- body += UnaryOperatorExpression(retKeyword, block[0]);
- } else {
- body = block;
- }
- exp = FunctionExpression(args, body);
- }
- default: exp = PartialFunctionExpression(ParseCallExpression());
- }
- ret exp;
- };
- ParsePatternMatchingExpression2 = @() {
- NextToken;
- patterns;
- Parens(testExp ParseExpression);
- System.Convert.ToInt64(_currentToken.Lexeme.Substring(2), 16);
- ret null;
- };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement