Differences From Artifact [fe545db0fb7a2428]:
- File        
polemy/parse.d
- 2010-11-07 10:32:59 - part of checkin [4198578702e] on branch trunk - Changed several documentation comments into ddoc compatible ones. (user: kinaba) [annotate]
 
 
To Artifact [a819ba1b27fdc13d]:
- File        
polemy/parse.d
- 2010-11-07 12:20:47 - part of checkin [5d4cb856d8] on branch trunk - Added FuncallExpression (user: kinaba) [annotate]
 
 
   90                  }                                                                     90                  }
   91          }                                                                             91          }
   92                                                                                        92  
   93          Expression parseExpression()                                                  93          Expression parseExpression()
   94          {                                                                             94          {
   95                  auto saved = lex.save;                                                95                  auto saved = lex.save;
   96                  scope(failure) lex = saved;                                           96                  scope(failure) lex = saved;
   97                                                                                   <
   98                  // Expr ::= E0                                                   <
   99                  // E0 ::= (E1 "=")* E1                                           <
  100                  // E1 ::= (E2 "+"|"-")* E2                                       <
  101                  // E2 ::= (E3 "*"|"/")* E3                                       <
  102                  // E3 ::= int | str | id | "(" Expr ")"                          <
  103                                                                                   <
  104                  return parseE0();                                                |    97                  return parseE(0);
  105          }                                                                             98          }
  106                                                                                        99  
  107          Expression parseE0()                                                     |   100          // [TODO] multi-char operators are not supported by the lexer...
  108          {                                                                        <
  109                  auto lhs = parseE1();                                            <
                                                                                        >   101          static immutable string[][] operator_perferences = [
                                                                                        >   102                  [","],
  110                  if( tryEat("=") )                                                |   103                  ["="], // caution! left associative
  111                          lhs = new BinOpExpression(lhs.pos, "=", lhs, parseE0()); |   104                  ["or"],
  112                  return lhs;                                                      |   105                  ["and"],
  113          }                                                                        <
                                                                                        >   106                  ["!="],
                                                                                        >   107                  ["=="],
                                                                                        >   108                  ["<","<=",">",">="],
                                                                                        >   109                  ["|"],
                                                                                        >   110                  ["^"],
                                                                                        >   111                  ["&"],
                                                                                        >   112                  ["<<", ">>"],
                                                                                        >   113                  ["+","-"],
                                                                                        >   114                  ["*","/","%"]
                                                                                        >   115          ];
  114                                                                                       116  
  115          Expression parseE1()                                                     |   117          Expression parseE(int level = 0)
  116          {                                                                            118          {
  117                  for(auto lhs = parseE2();;)                                      |   119                  if( operator_perferences.length <= level )
                                                                                        >   120                          return parseBaseExpression();
                                                                                        >   121                  else
  118                  {                                                                    122                  {
  119                          if( tryEat("+") )                                        |   123                          auto ops = operator_perferences[level];
  120                                  lhs = new BinOpExpression(lhs.pos, "+", lhs, par |   124                          auto e = parseE(level+1);
                                                                                        >   125                  seq:
                                                                                        >   126                          while( !lex.empty )
                                                                                        >   127                          {
                                                                                        >   128                                  auto pos = lex.front.pos;
                                                                                        >   129                                  foreach(op; ops)
  121                          else if( tryEat("-") )                                   |   130                                          if( tryEat(op) )
  122                                  lhs = new BinOpExpression(lhs.pos, "-", lhs, par <
                                                                                        >   131                                          {
                                                                                        >   132                                                  if( op == "=" ) // right assoc
                                                                                        >   133                                                          return new AssignExpress
  123                          else                                                     |   134                                                  else
                                                                                        >   135                                                          e = new FuncallExpressio
                                                                                        >   136                                                  continue seq;
                                                                                        >   137                                          }
                                                                                        >   138                                  break;
                                                                                        >   139                          }
  124                                  return lhs;                                      |   140                          return e;
  125                  }                                                                    141                  }
  126          }                                                                            142          }
  127                                                                                       143  
  128          Expression parseE2()                                                     |   144          Expression parseBaseExpression()
  129          {                                                                        <
  130                  for(auto lhs = parseE3();;)                                      <
  131                  {                                                                <
  132                          if( tryEat("*") )                                        <
  133                                  lhs = new BinOpExpression(lhs.pos, "*", lhs, par <
  134                          else if( tryEat("/") )                                   <
  135                                  lhs = new BinOpExpression(lhs.pos, "/", lhs, par <
  136                          else                                                     <
  137                                  return lhs;                                      <
  138                  }                                                                <
  139          }                                                                        <
  140                                                                                   <
  141          Expression parseE3()                                                     <
  142          {                                                                            145          {
  143                  if( lex.empty )                                                      146                  if( lex.empty )
  144                          throw new ParserException("EOF during parsing an express     147                          throw new ParserException("EOF during parsing an express
  145                  auto pos = lex.front.pos;                                            148                  auto pos = lex.front.pos;
  146                                                                                       149  
  147                  if( lex.front.kind == Token.Kind.number )                            150                  if( lex.front.kind == Token.Kind.number )
  148                  {                                                                    151                  {
................................................................................................................................................................................
  152                  if( lex.front.kind == Token.Kind.stringLiteral )                     155                  if( lex.front.kind == Token.Kind.stringLiteral )
  153                  {                                                                    156                  {
  154                          scope(exit) lex.popFront;                                    157                          scope(exit) lex.popFront;
  155                          return new StrLiteralExpression(pos, lex.front.str);         158                          return new StrLiteralExpression(pos, lex.front.str);
  156                  }                                                                    159                  }
  157                  if( tryEat("(") )                                                    160                  if( tryEat("(") )
  158                  {                                                                    161                  {
  159                          auto e = parseE0();                                      |   162                          auto e = parseE();
  160                          eat(")", "after parenthesized expression");                  163                          eat(")", "after parenthesized expression");
  161                          return e;                                                    164                          return e;
  162                  }                                                                    165                  }
  163                  scope(exit) lex.popFront;                                            166                  scope(exit) lex.popFront;
  164                  return new VarExpression(pos, lex.front.str);                        167                  return new VarExpression(pos, lex.front.str);
  165          }                                                                            168          }
  166                                                                                       169  
................................................................................................................................................................................
  207          auto p = parserFromString(`                                                  210          auto p = parserFromString(`
  208                  var zzz = 100; # comment                                             211                  var zzz = 100; # comment
  209                  zzz = zzz + zzz * "fo\no"; # comment                                 212                  zzz = zzz + zzz * "fo\no"; # comment
  210                          42;                                                          213                          42;
  211          `);                                                                          214          `);
  212                                                                                       215  
  213          auto s0 = new DeclStatement(null, "zzz", new IntLiteralExpression(null,      216          auto s0 = new DeclStatement(null, "zzz", new IntLiteralExpression(null, 
  214          auto s1 = new ExprStatement(null, new BinOpExpression(null, "=",         |   217          auto s1 = new ExprStatement(null, new AssignExpression(null,
  215                  new VarExpression(null, "zzz"),                                      218                  new VarExpression(null, "zzz"),
  216                  new BinOpExpression(null, "+",                                   |   219                  new FuncallExpression(null, new VarExpression(null,"+"),
  217                          new VarExpression(null, "zzz"),                              220                          new VarExpression(null, "zzz"),
  218                          new BinOpExpression(null, "*",                           |   221                          new FuncallExpression(null, new VarExpression(null,"*"),
  219                                  new VarExpression(null, "zzz"),                      222                                  new VarExpression(null, "zzz"),
  220                                  new StrLiteralExpression(null, "fo\\no")             223                                  new StrLiteralExpression(null, "fo\\no")
  221                                  ))));                                                224                                  ))));
  222          auto s2 = new ExprStatement(null, new IntLiteralExpression(null, BigInt(     225          auto s2 = new ExprStatement(null, new IntLiteralExpression(null, BigInt(
  223                                                                                       226  
  224          Program prog = p.parseProgram();                                             227          Program prog = p.parseProgram();
  225          assert( prog.length == 3 );                                                  228          assert( prog.length == 3 );
  226          assert( prog[0] == s0 );                                                     229          assert( prog[0] == s0 );
  227          assert( prog[1] == s1 );                                                     230          assert( prog[1] == s1 );
  228          assert( prog[2] == s2 );                                                     231          assert( prog[2] == s2 );
  229  }                                                                                    232  }