Mercurial > projects > dang
diff parser/Parser.d @ 172:01c2c49775ef
- Changed Parser to be more clean on type parsing.
- Parsing int function(int), and the like, types.(Function pointers)
- Fixed a design fault that made Symbol be wrong. Now Symbols are created with a factory with the help of types.
author | Anders Johnsen <skabet@gmail.com> |
---|---|
date | Thu, 24 Jul 2008 20:31:24 +0200 |
parents | 6cb2f4201e2a |
children | dc9bf56b7ace |
line wrap: on
line diff
--- a/parser/Parser.d Thu Jul 24 12:27:34 2008 +0200 +++ b/parser/Parser.d Thu Jul 24 20:31:24 2008 +0200 @@ -74,76 +74,61 @@ Decl parseDecl(Attribute att) { - Token t = peek; - - if (t.isBasicType || t.isIdentifier) + switch(peek.type) { - Id type; - Id iden; - int len = peekParseType; - if (peek(len).type == Tok.Identifier && len != 0) - { - type = parseType; -parseDeclAfterInvalidType: - iden = Id(require(Tok.Identifier)); - if ( isa(Tok.Seperator) ) + case Tok.Struct: + Id type = Id(next()); + Id iden = Id(require(Tok.Identifier)); + return parseStruct(type, iden, att); + + case Tok.Class: + Id type = Id(next()); + Id iden = Id(require(Tok.Identifier)); + return parseClass(type, iden, att); + + case Tok.Interface: + Id type = Id(next()); + Id iden = Id(require(Tok.Identifier)); + return parseInterface(type, iden, att); + + case Tok.Identifier: + Id type = parseType; + Id iden = Id(require(Tok.Identifier)); + + switch(peek.type) { - Token sep = next(); - return action.actOnDeclarator(type, iden, null, att); + case Tok.Seperator: + Token sep = next(); + return action.actOnDeclarator(type, iden, null, att); + + case Tok.Assign: + Token assign = next(); + Exp exp = parseExpression(); + require(Tok.Seperator); + return action.actOnDeclarator(type, iden, exp, att); + + case Tok.OpenParentheses: + return parseFunc(type, iden, att); + + default: + auto n1 = next(); + messages.report(UnexpectedTok, n1.location).arg(n1.getType); + return null; } - else if ( isa(Tok.Assign) ) - { - Token assign = next(); - Exp exp = parseExpression(); - require(Tok.Seperator); - return action.actOnDeclarator(type, iden, exp, att); - } - else if ( isa(Tok.OpenParentheses) ) - return parseFunc(type, iden, att); - else - { - auto n1 = next(); - messages.report(UnexpectedTok, n1.location).arg(n1.getType); - } + messages.report(InvalidDeclType, peek.location) + .arg(sm.getText(peek.asRange)); + + default: + if (peek.isBasicType) + goto case Tok.Identifier; + + messages.report(UnexpectedTok, peek.location) + .arg(sm.getText(peek.asRange)); + return null; - } - t = peek(len); - messages.report(InvalidDeclType, t.location) - .arg(sm.getText(t.asRange)); - while(len--) - next(); - while( !isa(Tok.Identifier) && !isa(Tok.EOF)) - next(); - if ( isa(Tok.EOF ) ) - messages.report(UnexpectedTok, t.location) - .fatal(ExitLevel.Parser); - - type = Id(peek); - goto parseDeclAfterInvalidType; } - else if (t.type == Tok.Struct) - { - Id type = Id(next()); - Id iden = Id(require(Tok.Identifier)); - - return parseStruct(type, iden, att); - } - else if (t.type == Tok.Class) - { - Id type = Id(next()); - Id iden = Id(require(Tok.Identifier)); - - return parseClass(type, iden, att); - } - else if (t.type == Tok.Interface) - { - Id type = Id(next()); - Id iden = Id(require(Tok.Identifier)); - - return parseInterface(type, iden, att); - } - messages.report(UnexpectedTok, t.location) - .arg(t.getType) + messages.report(UnexpectedTok, peek.location) + .arg(peek.getType) .arg(Tok.Identifier) .fatal(ExitLevel.Parser); } @@ -536,169 +521,175 @@ */ Stmt parseStatement() { - Token t = peek; - - if (t.isReturn) - { - Token ret = next(); - Exp exp; - if (peek.type != Tok.Seperator) - exp = parseExpression(); - require(Tok.Seperator); - return action.actOnReturnStmt(ret, exp); - } - /* - if (cond) - single statement | compound statement - [else - single statement | compound statement] - */ - else if (t.isIf) - { - Token _if = next(); - - require(Tok.OpenParentheses); - Exp cond = parseExpression(); - require(Tok.CloseParentheses); - - Stmt thenB = parseSingleOrCompoundStatement(); - - // if there is no else part we use the if as token, to have - // something than can be passed along - Token _else = _if; - Stmt elseB; - if (peek.type == Tok.Else) - { - _else = next(); - elseB = parseSingleOrCompoundStatement(); - } - - return action.actOnIfStmt(_if, cond, thenB, _else, elseB); - - } - /* - while (cond) - single statement | compound statement - */ - else if (t.isWhile) - { - Token _while = next(); - require(Tok.OpenParentheses); - Exp cond = parseExpression(); - require(Tok.CloseParentheses); - Stmt bodyStmt = parseSingleOrCompoundStatement(); - return action.actOnWhileStmt(_while, cond, bodyStmt); - - } - else if (t.isFor) + switch (peek.type) { - Token _for = next(); - require(Tok.OpenParentheses); - Stmt init; - if ( isa(Tok.Seperator)) + case Tok.Return: + Token ret = next(); + Exp exp; + if (peek.type != Tok.Seperator) + exp = parseExpression(); require(Tok.Seperator); - else - init = parseStatement(); + return action.actOnReturnStmt(ret, exp); + + case Tok.If: + Token _if = next(); + + require(Tok.OpenParentheses); + Exp cond = parseExpression(); + require(Tok.CloseParentheses); + + Stmt thenB = parseSingleOrCompoundStatement(); - Exp cond; - if ( !isa(Tok.Seperator)) - cond = parseExpression(); - require(Tok.Seperator); + // if there is no else part we use the if as token, to have + // something than can be passed along + Token _else = _if; + Stmt elseB; + if (peek.type == Tok.Else) + { + _else = next(); + elseB = parseSingleOrCompoundStatement(); + } + return action.actOnIfStmt(_if, cond, thenB, _else, elseB); - Exp incre; - if ( !isa(Tok.CloseParentheses)) - incre = parseExpression(); - require(Tok.CloseParentheses); + case Tok.While: + Token _while = next(); + require(Tok.OpenParentheses); + Exp cond = parseExpression(); + require(Tok.CloseParentheses); + Stmt bodyStmt = parseSingleOrCompoundStatement(); + return action.actOnWhileStmt(_while, cond, bodyStmt); + + case Tok.For: + Token _for = next(); + require(Tok.OpenParentheses); + Stmt init; + if ( isa(Tok.Seperator)) + require(Tok.Seperator); + else + init = parseStatement(); - Stmt bodyStmt = parseSingleOrCompoundStatement(); - return action.actOnForStmt(_for, init, cond, incre, bodyStmt); - } - else if (t.isBasicType || t.isIdentifier) - { - Token iden = peek; - Token n = peek(1); - // Must be an decl, if we start with a basic type, or two - // identifiers in a row - if ( n.type == Tok.Star || n.type == Tok.OpenBracket) - { - int len = peekParseType; - if(peek(len).type == Tok.Identifier && len != 0) - return action.actOnDeclStmt(parseVarDecl()); + Exp cond; + if ( !isa(Tok.Seperator)) + cond = parseExpression(); + require(Tok.Seperator); - Exp exp = parseExpression(); - require(Tok.Seperator); - return action.actOnExprStmt(exp); - } + Exp incre; + if ( !isa(Tok.CloseParentheses)) + incre = parseExpression(); + require(Tok.CloseParentheses); + + Stmt bodyStmt = parseSingleOrCompoundStatement(); + return action.actOnForStmt(_for, init, cond, incre, bodyStmt); - if (n.isIdentifier()) - return action.actOnDeclStmt(parseVarDecl()); + case Tok.Switch: + auto t = next(); + require(Tok.OpenParentheses); + auto target = parseExpression(); + auto res = action.actOnStartOfSwitchStmt(t, target); + require(Tok.CloseParentheses); + require(Tok.OpenBrace); + while (true) + { + Stmt[] statements; + if (isa(Tok.Default)) + { + Token _default = next(); + require(Tok.Colon); + statements.length = 0; + while (peek.type != Tok.Case + && peek.type != Tok.Default + && peek.type != Tok.CloseBrace) + statements ~= parseStatement(); + action.actOnDefaultStmt(res, _default, statements); + continue; + } - // Expression: a.b, a = b, a(b) etc. - Exp exp = parseExpression(); - require(Tok.Seperator); - return action.actOnExprStmt(exp); - } - else if (t.isSwitch) - { - next(); - require(Tok.OpenParentheses); - auto target = parseExpression(); - auto res = action.actOnStartOfSwitchStmt(t, target); - require(Tok.CloseParentheses); - require(Tok.OpenBrace); - while (true) - { - Stmt[] statements; - if (isa(Tok.Default)) - { - Token _default = next(); + Token _case = peek; + if (_case.type != Tok.Case) + break; + next(); + + Exp[] literals; + do + { + Exp e = parseExpression(); + literals ~= e; + } + while (skip(Tok.Comma)); require(Tok.Colon); - statements.length = 0; + while (peek.type != Tok.Case && peek.type != Tok.Default && peek.type != Tok.CloseBrace) statements ~= parseStatement(); - action.actOnDefaultStmt(res, _default, statements); - continue; + + action.actOnCaseStmt(res, _case, literals, statements); + + if (peek.type == Tok.CloseBrace) + break; + } + require(Tok.CloseBrace); + return res; + + case Tok.Star: + auto exp = parseExpression(); + require(Tok.Seperator); + return action.actOnExprStmt(exp); + + case Tok.Identifier: + // If it's a '*' it must be a method. Otherwise it won't give + // any sense. + if (isa(Tok.Function, 1) || + isa(Tok.Identifier, 1) || + isa(Tok.Star, 1)) + return action.actOnDeclStmt(parseDecl(Attribute())); + + if (isa(Tok.OpenBracket, 1)) + { + int i = 1; + while (isa(Tok.OpenBracket, i) || + isa(Tok.Star, i) || + isa(Tok.Identifier, i)) + { + if (isa(Tok.Identifier, i)) + return action.actOnDeclStmt(parseDecl(Attribute())); + + i++; + if (isa(Tok.Star,i-1)) + continue; + // Must be OpenBracket here.. + + if (isa(Tok.Integer, i)) + i++; + else + if (isa(Tok.CloseBracket, i)) + return action.actOnDeclStmt(parseDecl(Attribute())); + else + i++; + + if (!isa(Tok.CloseBracket, i)) + break; + i++; + } + if (isa(Tok.Function, i)) + return action.actOnDeclStmt(parseDecl(Attribute())); } - Token _case = peek; - if (_case.type != Tok.Case) - break; - next(); - - Exp[] literals; - do - { - Exp e = parseExpression(); - literals ~= e; - } - while (skip(Tok.Comma)); - require(Tok.Colon); - - while (peek.type != Tok.Case - && peek.type != Tok.Default - && peek.type != Tok.CloseBrace) - statements ~= parseStatement(); + // Expression: a.b, a = b, a(b) etc. + Exp exp = parseExpression(); + require(Tok.Seperator); + return action.actOnExprStmt(exp); + + case Tok.Void: // And all basic types + return action.actOnDeclStmt(parseVarDecl()); - action.actOnCaseStmt(res, _case, literals, statements); + default: + if (peek.isBasicType) + goto case Tok.Void; - if (peek.type == Tok.CloseBrace) - break; - } - require(Tok.CloseBrace); - return res; - } - else if (t.type == Tok.Star) - { - auto exp = parseExpression(); - require(Tok.Seperator); - return action.actOnExprStmt(exp); - } - else - { - messages.report(UnexpectedBeginStmt, t.location).arg(t.getType); - return null; + messages.report(UnexpectedBeginStmt, peek.location).arg(peek.getType); + require(Tok.Seperator); + return null; } } @@ -833,70 +824,56 @@ messages.report(InvalidType, type.location); currentType = Id(type); - type = peek; - while(type.type == Tok.Star || type.type == Tok.OpenBracket) + while(true) { - if(type.type == Tok.Star) - { - currentType = PointerId(currentType); - next(); - } - else + switch(peek.type) { - next(); - if(peek.type == Tok.Integer) - currentType = StaticArrayId( - currentType, - action.actOnNumericConstant( - require(Tok.Integer))); - require(Tok.CloseBracket); + case Tok.Star: + currentType = PointerTypeId(currentType); + next(); + break; + case Tok.OpenBracket: + next(); + if (isa(Tok.Integer)) + currentType = StaticArrayTypeId( + currentType, + action.actOnNumericConstant( + require(Tok.Integer))); + require(Tok.CloseBracket); + break; + case Tok.Function: + next(); - } - type = peek; - } - return currentType; - } - - int peekParseType() - { - int i; - Token type = peek(i); + require(Tok.OpenParentheses); // Remove the "(" token. - Id currentType; + DeclT[] decls; - if ( !(type.isBasicType || type.type == Tok.Identifier) ) - return 0; + while(peek.type != Tok.CloseParentheses) + { + auto t = parseType(); + Id i; + if(peek.type == Tok.Identifier) + i = parseIdentifier(); - currentType = Id(type); - type = peek(++i); + // Act on function type param + decls ~= action.actOnDeclarator(t, i, null, Attribute()); + + if(peek.type == Tok.Comma) + next(); + } - while(type.type == Tok.Star || type.type == Tok.OpenBracket) - { - if(type.type == Tok.Star) - { - i++; + currentType = FunctionTypeId(currentType, decls); + + require(Tok.CloseParentheses); // Remove the ")" + break; + default: + goto end; } - else - { - if(peek(i++).type != Tok.OpenBracket) - return 0; - if(peek(i).type == Tok.Integer) - { - i++; - if(peek(i++).type != Tok.CloseBracket) - return 0; - } - else - if(peek(i++).type != Tok.CloseBracket) - return 0; - - } - type = peek(i); } - - return i; +end: + return currentType; } private: @@ -1143,9 +1120,9 @@ return true; } - bool isa(Tok t) + bool isa(Tok t, int i = 0) { - return peek.type == t; + return peek(i).type == t; } Token next()