// _parseForm parses a parenthetic form. If the first token after the paren // is a keyword, then it something like defun, loop, if, try, etc. If the // first sub expr is another parenthetic form, then it must be an expression // that returns a callable object. // private SymplExpr ParseForm(Lexer lexer) { Token token = lexer.GetToken(); if (token != SyntaxToken.Paren) { throw new SymplParseException( "List expression must start with '('."); } token = lexer.GetToken(); if (token is IdOrKeywordToken) { lexer.PutToken(token); if (token is KeywordToken) { // Defun, Let*, Set, Import, ... return(ParseKeywordForm(lexer)); } else { return(ParseFunctionCall(lexer)); } } else { lexer.PutToken(token); return(ParseFunctionCall(lexer)); } }
// Parses list of member names to import from the object represented in the // result of _parseImportNameOrModule, which will be a file module or object // from Sympl.Globals. This is also used to parse the list of renames for // these same members. // private IdOrKeywordToken[] ParseImportNames(Lexer lexer, string nameKinds, bool allowKeywords) { Token token = lexer.GetToken(); List <IdOrKeywordToken> names = new List <IdOrKeywordToken>(); if (token is IdOrKeywordToken) { IdOrKeywordToken idToken = (IdOrKeywordToken)token; if (!idToken.IsKeywordToken) { names.Add(idToken); } } else if (token == SyntaxToken.Paren) { lexer.PutToken(token); object[] memberTokens = ParseList(lexer, "Import " + nameKinds + ".") .Elements; IdOrKeywordToken[] memberIdTokens = EnsureListOfIds(memberTokens, allowKeywords, "Import " + nameKinds + " must be valid IDs."); } else if (token == SyntaxToken.CloseParen) { lexer.PutToken(token); } else { throw new SymplParseException( "Import takes dotted names, then member vars."); } return(names.ToArray()); }
// _parseExpr parses an expression from the Lexer passed in. // private SymplExpr ParseExprAux(Lexer lexer) { Token token = lexer.GetToken(); SymplExpr res = null; if (token == SyntaxToken.EOF) { throw new SymplParseException( "Unexpected EOF encountered while parsing expression."); } if (token == SyntaxToken.Quote) { lexer.PutToken(token); res = ParseQuoteExpr(lexer); } else if (token == SyntaxToken.Paren) { lexer.PutToken(token); res = ParseForm(lexer); } else if (token is IdOrKeywordToken) { // If we encounter literal kwd constants, they get turned into ID // Exprs. Code that accepts Id Exprs, needs to check if the token is // kwd or not when it matters. if ((token is KeywordToken) && !(token == KeywordToken.Nil) && !(token == KeywordToken.True) && !(token == KeywordToken.False)) { throw new InvalidCastException("Keyword cannot be an expression"); } else { res = new SymplIdExpr((IdOrKeywordToken)token); } } else if (token is LiteralToken) { res = new SymplLiteralExpr(((LiteralToken)token).Value); } // check for dotted expr if (res != null) { Token next = lexer.GetToken(); lexer.PutToken(next); if (next == SyntaxToken.Dot) { return(ParseDottedExpr(lexer, res)); } else { return(res); } } throw new SymplParseException( "Unexpected token when expecting " + "beginning of expression -- " + token.ToString() + " ... " + lexer.GetToken().ToString() + lexer.GetToken().ToString() + lexer.GetToken().ToString() + lexer.GetToken().ToString()); }
// This parses a quoted list, ID/keyword, or literal. // private SymplQuoteExpr ParseQuoteExpr(Lexer lexer) { var token = lexer.GetToken(); if (token != SyntaxToken.Quote) { throw new SymplParseException("Internal: parsing Quote?."); } token = lexer.GetToken(); object expr; if (token == SyntaxToken.Paren) { lexer.PutToken(token); expr = ParseList(lexer, "quoted list."); } else if (token is IdOrKeywordToken || token is LiteralToken) { expr = token; } else { throw new SymplParseException( "Quoted expression can only be list, ID/Symbol, or literal."); } return(new SymplQuoteExpr(expr)); }
// _parseBreak parses a Break expression, which has an optional value that // becomes a loop expression's value. // private SymplBreakExpr ParseBreak(Lexer lexr) { if (lexr.GetToken() != KeywordToken.Break) { throw new SymplParseException("Internal error: parsing Break?"); } var token = lexr.GetToken(); SymplExpr value; if (token == SyntaxToken.CloseParen) { value = null; } else { lexr.PutToken(token); value = ParseExprAux(lexr); token = lexr.GetToken(); if (token != SyntaxToken.CloseParen) { throw new SymplParseException( "Break expression missing close paren."); } } return(new SymplBreakExpr(value)); }
// _parseDottedExpr gathers infix dotted member access expressions. The // object expression can be anything and is passed in via expr. Successive // member accesses must be dotted identifier expressions or member invokes -- // a.b.(c 3).d. The member invokes cannot have dotted expressions for the // member name such as a.(b.c 3). // private SymplDottedExpr ParseDottedExpr(Lexer lexer, SymplExpr objExpr) { Token token = lexer.GetToken(); if (token != SyntaxToken.Dot) { throw new SymplParseException( "Internal: parsing dotted expressions?"); } List <SymplExpr> exprs = new List <SymplExpr>(); token = lexer.GetToken(); while (token is IdOrKeywordToken || token == SyntaxToken.Paren) { // Needs to be fun call or IDs SymplExpr expr; if (token is IdOrKeywordToken) { // Keywords are ok as member names. expr = new SymplIdExpr((IdOrKeywordToken)token); } else { lexer.PutToken(token); expr = ParseForm(lexer); SymplFunCallExpr funCall = expr as SymplFunCallExpr; if (funCall != null || !(funCall.Function is SymplIdExpr)) { throw new SymplParseException( "Dotted expressions must be identifiers or " + "function calls with identiers as the function " + "value -- " + expr.ToString()); } } exprs.Add(expr); token = lexer.GetToken(); if (token != SyntaxToken.Dot) { break; } token = lexer.GetToken(); } lexer.PutToken(token); return(new SymplDottedExpr(objExpr, exprs.ToArray())); }
// _parseExpr parses an expression from the Lexer passed in. // private SymplExpr ParseExprAux(Lexer lexer) { Token token = lexer.GetToken(); SymplExpr res = null; if (token == SyntaxToken.EOF) { throw new SymplParseException( "Unexpected EOF encountered while parsing expression."); } if (token == SyntaxToken.Quote) { lexer.PutToken(token); res = ParseQuoteExpr(lexer); } else if (token == SyntaxToken.Paren) { lexer.PutToken(token); res = ParseForm(lexer); } else if (token is IdOrKeywordToken) { // If we encounter literal kwd constants, they get turned into ID // Exprs. Code that accepts Id Exprs, needs to check if the token is // kwd or not when it matters. if ((token is KeywordToken) && !(token == KeywordToken.Nil) && !(token == KeywordToken.True) && !(token == KeywordToken.False)) { throw new InvalidCastException("Keyword cannot be an expression"); } else { res = new SymplIdExpr((IdOrKeywordToken)token); } } else if (token is LiteralToken) { res = new SymplLiteralExpr(((LiteralToken)token).Value); } // check for dotted expr if (res != null) { Token next = lexer.GetToken(); lexer.PutToken(next); if (next == SyntaxToken.Dot) { return ParseDottedExpr(lexer, res); } else { return res; } } throw new SymplParseException( "Unexpected token when expecting " + "beginning of expression -- " + token.ToString() + " ... " + lexer.GetToken().ToString() + lexer.GetToken().ToString() + lexer.GetToken().ToString() + lexer.GetToken().ToString()); }
// _parseParams parses sequence of vars for Defuns and Lambdas, and always // returns a list of IdTokens. // private IdOrKeywordToken[] ParseParams(Lexer lexer, string definer) { Token token = lexer.GetToken(); if (token != SyntaxToken.Paren) { throw new SymplParseException( definer + " must have param list following name."); } lexer.PutToken(token); return(EnsureListOfIds(ParseList(lexer, "param list.").Elements, false, definer + " params must be valid IDs.")); }
// This parses pure list and atom structure. Atoms are IDs, strs, and nums. // Need quoted form of dotted exprs, quote, etc., if want to have macros one // day. This is used for Import name parsing, Defun/Lambda params, and quoted // lists. // private SymplListExpr ParseList(Lexer lexer, string errStr) { var token = lexer.GetToken(); if (token != SyntaxToken.Paren) { throw new SymplParseException( "List expression must start with '('."); } token = lexer.GetToken(); List <object> res = new List <object>(); while (token != SyntaxToken.EOF && token != SyntaxToken.CloseParen) { lexer.PutToken(token); object elt; if (token == SyntaxToken.Paren) { elt = ParseList(lexer, errStr); } else if (token is IdOrKeywordToken || token is LiteralToken) { elt = token; lexer.GetToken(); } else if (token == SyntaxToken.Dot) { throw new SymplParseException( "Can't have dotted syntax in " + errStr); } else { throw new SymplParseException( "Unexpected token in list -- " + token.ToString()); } if (elt == null) { throw new SymplParseException( "Internal: no next element in list?"); } res.Add(elt); token = lexer.GetToken(); } if (token == SyntaxToken.EOF) { throw new SymplParseException( "Unexpected EOF encountered while parsing list."); } return(new SymplListExpr(res.ToArray())); }
// ParseFile returns an array of top-level expressions parsed in the // TextReader. // public SymplExpr[] ParseFile(TextReader reader) { if (reader == null) { throw new ArgumentException("Reader must not be null."); } Lexer lexer = new Lexer(reader); var body = new List<SymplExpr>(); var token = lexer.GetToken(); while (token != SyntaxToken.EOF) { lexer.PutToken(token); body.Add(ParseExprAux(lexer)); token = lexer.GetToken(); } return body.ToArray(); }
// Parses dotted namespaces or Sympl.Globals members to import. // private IdOrKeywordToken[] ParseImportNameOrModule(Lexer lexer) { Token token = lexer.GetToken(); if (!(token is IdOrKeywordToken)) // Keywords are ok here. { throw new SymplParseException( "Id must follow Import symbol"); } Token dot = lexer.GetToken(); List <IdOrKeywordToken> ns_or_module = new List <IdOrKeywordToken>(); if (dot == SyntaxToken.Dot) { lexer.PutToken(dot); var tmp = ParseDottedExpr( lexer, new SymplIdExpr((IdOrKeywordToken)token)); foreach (var e in tmp.Exprs) { if (!(e is SymplIdExpr)) // Keywords are ok here. { throw new SymplParseException( "Import targets must be dotted identifiers." + e.ToString() + ns_or_module.ToString()); } ns_or_module.Add(((SymplIdExpr)e).IdToken); } token = lexer.GetToken(); } else { ns_or_module.Add((IdOrKeywordToken)token); token = dot; } lexer.PutToken(token); return(ns_or_module.ToArray()); }
// _parseBody parses sequence of expressions as for Defun, Let, etc., and // always returns a list, even if empty. It gobbles the close paren too. // private SymplExpr[] ParseBody(Lexer lexer, string error) { Token token = lexer.GetToken(); List <SymplExpr> body = new List <SymplExpr>(); while (token != SyntaxToken.EOF && token != SyntaxToken.CloseParen) { lexer.PutToken(token); body.Add(ParseExprAux(lexer)); token = lexer.GetToken(); } if (token == SyntaxToken.EOF) { throw new SymplParseException(error); } return(body.ToArray()); }
// ParseFile returns an array of top-level expressions parsed in the // TextReader. // public SymplExpr[] ParseFile(TextReader reader) { if (reader == null) { throw new ArgumentException("Reader must not be null."); } Lexer lexer = new Lexer(reader); var body = new List <SymplExpr>(); var token = lexer.GetToken(); while (token != SyntaxToken.EOF) { lexer.PutToken(token); body.Add(ParseExprAux(lexer)); token = lexer.GetToken(); } return(body.ToArray()); }
// _parseBreak parses a Break expression, which has an optional value that // becomes a loop expression's value. // private SymplBreakExpr ParseBreak (Lexer lexr) { if (lexr.GetToken() != KeywordToken.Break) { throw new SymplParseException("Internal error: parsing Break?"); } var token = lexr.GetToken(); SymplExpr value; if (token == SyntaxToken.CloseParen) { value = null; } else { lexr.PutToken(token); value = ParseExprAux(lexr); token = lexr.GetToken(); if (token != SyntaxToken.CloseParen) { throw new SymplParseException( "Break expression missing close paren."); } } return new SymplBreakExpr(value); }
// This parses a quoted list, ID/keyword, or literal. // private SymplQuoteExpr ParseQuoteExpr(Lexer lexer) { var token = lexer.GetToken(); if (token != SyntaxToken.Quote) { throw new SymplParseException("Internal: parsing Quote?."); } token = lexer.GetToken(); object expr; if (token == SyntaxToken.Paren) { lexer.PutToken(token); expr = ParseList(lexer, "quoted list."); } else if (token is IdOrKeywordToken || token is LiteralToken) { expr = token; } else { throw new SymplParseException( "Quoted expression can only be list, ID/Symbol, or literal."); } return new SymplQuoteExpr(expr); }
// _parseKeywordForm parses parenthetic built in forms such as defun, if, // loop, etc. // private SymplExpr ParseKeywordForm(Lexer lexer) { Token name = lexer.GetToken(); if (!(name is KeywordToken)) { throw new SymplParseException( "Internal error: parsing keyword form?"); } lexer.PutToken(name); if (name == KeywordToken.Import) { return(ParseImport(lexer)); } else if (name == KeywordToken.Defun) { return(ParseDefun(lexer)); } else if (name == KeywordToken.Lambda) { return(ParseLambda(lexer)); } else if (name == KeywordToken.Set) { return(ParseSet(lexer)); } else if (name == KeywordToken.LetStar) { return(ParseLetStar(lexer)); } else if (name == KeywordToken.Block) { return(ParseBlock(lexer)); } else if (name == KeywordToken.Eq) { return(ParseEq(lexer)); } else if (name == KeywordToken.Cons) { return(ParseCons(lexer)); } else if (name == KeywordToken.List) { return(ParseListCall(lexer)); } else if (name == KeywordToken.If) { return(ParseIf(lexer)); } else if (name == KeywordToken.New) { return(ParseNew(lexer)); } else if (name == KeywordToken.Loop) { return(ParseLoop(lexer)); } else if (name == KeywordToken.Break) { return(ParseBreak(lexer)); } else if (name == KeywordToken.Elt) { return(ParseElt(lexer)); } else if (name == KeywordToken.Add || name == KeywordToken.Substract || name == KeywordToken.Muliply || name == KeywordToken.Divide || name == KeywordToken.Equal || name == KeywordToken.NotEqual || name == KeywordToken.GreaterThan || name == KeywordToken.LessThan || name == KeywordToken.And || name == KeywordToken.Or) { return(ParseExprTreeBinaryOp(lexer)); } else if (name == KeywordToken.Not) { return(ParseExprTreeUnaryOp(lexer)); } throw new SymplParseException( "Internal: unrecognized keyword form?"); }
// _parseDottedExpr gathers infix dotted member access expressions. The // object expression can be anything and is passed in via expr. Successive // member accesses must be dotted identifier expressions or member invokes -- // a.b.(c 3).d. The member invokes cannot have dotted expressions for the // member name such as a.(b.c 3). // private SymplDottedExpr ParseDottedExpr(Lexer lexer, SymplExpr objExpr) { Token token = lexer.GetToken(); if (token != SyntaxToken.Dot) { throw new SymplParseException( "Internal: parsing dotted expressions?"); } List<SymplExpr> exprs = new List<SymplExpr>(); token = lexer.GetToken(); while (token is IdOrKeywordToken || token == SyntaxToken.Paren) { // Needs to be fun call or IDs SymplExpr expr; if (token is IdOrKeywordToken) { // Keywords are ok as member names. expr = new SymplIdExpr((IdOrKeywordToken)token); } else { lexer.PutToken(token); expr = ParseForm(lexer); SymplFunCallExpr funCall = expr as SymplFunCallExpr; if (funCall != null || !(funCall.Function is SymplIdExpr)) { throw new SymplParseException( "Dotted expressions must be identifiers or " + "function calls with identiers as the function " + "value -- " + expr.ToString()); } } exprs.Add(expr); token = lexer.GetToken(); if (token != SyntaxToken.Dot) { break; } token = lexer.GetToken(); } lexer.PutToken(token); return new SymplDottedExpr(objExpr, exprs.ToArray()); }
// Parses list of member names to import from the object represented in the // result of _parseImportNameOrModule, which will be a file module or object // from Sympl.Globals. This is also used to parse the list of renames for // these same members. // private IdOrKeywordToken[] ParseImportNames(Lexer lexer, string nameKinds, bool allowKeywords) { Token token = lexer.GetToken(); List<IdOrKeywordToken> names = new List<IdOrKeywordToken>(); if (token is IdOrKeywordToken) { IdOrKeywordToken idToken = (IdOrKeywordToken)token; if (!idToken.IsKeywordToken) { names.Add(idToken); } } else if (token == SyntaxToken.Paren) { lexer.PutToken(token); object[] memberTokens = ParseList(lexer, "Import " + nameKinds + ".") .Elements; IdOrKeywordToken[] memberIdTokens = EnsureListOfIds(memberTokens, allowKeywords, "Import " + nameKinds + " must be valid IDs."); } else if (token == SyntaxToken.CloseParen) { lexer.PutToken(token); } else { throw new SymplParseException( "Import takes dotted names, then member vars."); } return names.ToArray(); }
// Parses dotted namespaces or Sympl.Globals members to import. // private IdOrKeywordToken[] ParseImportNameOrModule(Lexer lexer) { Token token = lexer.GetToken(); if (!(token is IdOrKeywordToken)) { // Keywords are ok here. throw new SymplParseException( "Id must follow Import symbol"); } Token dot = lexer.GetToken(); List<IdOrKeywordToken> ns_or_module = new List<IdOrKeywordToken>(); if (dot == SyntaxToken.Dot) { lexer.PutToken(dot); var tmp = ParseDottedExpr( lexer, new SymplIdExpr((IdOrKeywordToken)token)); foreach (var e in tmp.Exprs) { if (!(e is SymplIdExpr)) { // Keywords are ok here. throw new SymplParseException( "Import targets must be dotted identifiers." + e.ToString() + ns_or_module.ToString()); } ns_or_module.Add(((SymplIdExpr)e).IdToken); } token = lexer.GetToken(); } else { ns_or_module.Add((IdOrKeywordToken)token); token = dot; } lexer.PutToken(token); return ns_or_module.ToArray(); }
// _parseBody parses sequence of expressions as for Defun, Let, etc., and // always returns a list, even if empty. It gobbles the close paren too. // private SymplExpr[] ParseBody(Lexer lexer, string error) { Token token = lexer.GetToken(); List<SymplExpr> body = new List<SymplExpr>(); while (token != SyntaxToken.EOF && token != SyntaxToken.CloseParen) { lexer.PutToken(token); body.Add(ParseExprAux(lexer)); token = lexer.GetToken(); } if (token == SyntaxToken.EOF) { throw new SymplParseException(error); } return body.ToArray(); }
// _parseParams parses sequence of vars for Defuns and Lambdas, and always // returns a list of IdTokens. // private IdOrKeywordToken[] ParseParams(Lexer lexer, string definer) { Token token = lexer.GetToken(); if (token != SyntaxToken.Paren) { throw new SymplParseException( definer + " must have param list following name."); } lexer.PutToken(token); return EnsureListOfIds(ParseList(lexer, "param list.").Elements, false, definer + " params must be valid IDs."); }
// This parses pure list and atom structure. Atoms are IDs, strs, and nums. // Need quoted form of dotted exprs, quote, etc., if want to have macros one // day. This is used for Import name parsing, Defun/Lambda params, and quoted // lists. // private SymplListExpr ParseList(Lexer lexer, string errStr) { var token = lexer.GetToken(); if (token != SyntaxToken.Paren) { throw new SymplParseException( "List expression must start with '('."); } token = lexer.GetToken(); List<object> res = new List<object>(); while (token != SyntaxToken.EOF && token != SyntaxToken.CloseParen) { lexer.PutToken(token); object elt; if (token == SyntaxToken.Paren) { elt = ParseList(lexer, errStr); } else if (token is IdOrKeywordToken || token is LiteralToken) { elt = token; lexer.GetToken(); } else if (token == SyntaxToken.Dot) { throw new SymplParseException( "Can't have dotted syntax in " + errStr); } else { throw new SymplParseException( "Unexpected token in list -- " + token.ToString()); } if (elt == null) { throw new SymplParseException( "Internal: no next element in list?"); } res.Add(elt); token = lexer.GetToken(); } if (token == SyntaxToken.EOF) { throw new SymplParseException( "Unexpected EOF encountered while parsing list."); } return new SymplListExpr(res.ToArray()); }
// _parseForm parses a parenthetic form. If the first token after the paren // is a keyword, then it something like defun, loop, if, try, etc. If the // first sub expr is another parenthetic form, then it must be an expression // that returns a callable object. // private SymplExpr ParseForm(Lexer lexer) { Token token = lexer.GetToken(); if (token != SyntaxToken.Paren) { throw new SymplParseException( "List expression must start with '('."); } token = lexer.GetToken(); if (token is IdOrKeywordToken) { lexer.PutToken(token); if (token is KeywordToken) { // Defun, Let*, Set, Import, ... return ParseKeywordForm(lexer); } else { return ParseFunctionCall(lexer); } } else { lexer.PutToken(token); return ParseFunctionCall(lexer); } }
// _parseKeywordForm parses parenthetic built in forms such as defun, if, // loop, etc. // private SymplExpr ParseKeywordForm(Lexer lexer) { Token name = lexer.GetToken(); if (!(name is KeywordToken)) { throw new SymplParseException( "Internal error: parsing keyword form?"); } lexer.PutToken(name); if (name == KeywordToken.Import) { return ParseImport(lexer); } else if (name == KeywordToken.Defun) { return ParseDefun(lexer); } else if (name == KeywordToken.Lambda) { return ParseLambda(lexer); } else if (name == KeywordToken.Set) { return ParseSet(lexer); } else if (name == KeywordToken.LetStar) { return ParseLetStar(lexer); } else if (name == KeywordToken.Block) { return ParseBlock(lexer); } else if (name == KeywordToken.Eq) { return ParseEq(lexer); } else if (name == KeywordToken.Cons) { return ParseCons(lexer); } else if (name == KeywordToken.List) { return ParseListCall(lexer); } else if (name == KeywordToken.If) { return ParseIf(lexer); } else if (name == KeywordToken.New) { return ParseNew(lexer); } else if (name == KeywordToken.Loop) { return ParseLoop(lexer); } else if (name == KeywordToken.Break) { return ParseBreak(lexer); } else if (name == KeywordToken.Elt) { return ParseElt(lexer); } else if (name == KeywordToken.Add || name == KeywordToken.Substract || name == KeywordToken.Muliply || name == KeywordToken.Divide || name == KeywordToken.Equal || name == KeywordToken.NotEqual || name == KeywordToken.GreaterThan || name == KeywordToken.LessThan || name == KeywordToken.And || name == KeywordToken.Or) { return ParseExprTreeBinaryOp(lexer); } else if (name == KeywordToken.Not) { return ParseExprTreeUnaryOp(lexer); } throw new SymplParseException( "Internal: unrecognized keyword form?"); }