From: TimePath Date: Sat, 9 Sep 2017 02:06:13 +0000 (+1000) Subject: A bit more progress X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=0f9e3d159c80cb5b5578c10d8591621cd9261499;p=xonotic%2Fgmqcc.git A bit more progress --- diff --git a/lexer.cpp b/lexer.cpp index 28134e2..2e7277b 100644 --- a/lexer.cpp +++ b/lexer.cpp @@ -1124,6 +1124,25 @@ Token lex_do(lex_file *lex) lex_ungetch(lex, nextch); } +#define MERGE(c, a, b) \ + if (ch == Token::a) { \ + nextch = lex_getch(lex); \ + if (nextch == Token::b) { \ + lex_tokench(lex, ch); \ + lex_tokench(lex, nextch); \ + lex_endtoken(lex); \ + return (lex->tok.ttype = Token::c); \ + } \ + lex_ungetch(lex, nextch); \ + } + + MERGE(OP_AND, AND, AND) // && + MERGE(OP_CROSS, GT, LT) // >< + MERGE(OP_LE, LT, EQ) // <= + MERGE(OP_GE, GT, EQ) // >= + MERGE(OP_LSH, LT, LT) // << + MERGE(OP_RSH, GT, GT) // >> + if (lex->flags.noops) { /* Detect characters early which are normally diff --git a/lexer.h b/lexer.h index a98cee3..f75dff6 100644 --- a/lexer.h +++ b/lexer.h @@ -42,6 +42,12 @@ X(IDENT, ) \ X(TYPENAME, ) \ X(OPERATOR, ) \ + X(OP_AND, ) \ + X(OP_CROSS, ) \ + X(OP_LE, ) \ + X(OP_GE, ) \ + X(OP_LSH, ) \ + X(OP_RSH, ) \ /* loop */ \ X(KEYWORD, ) \ /* 3 dots, ... */ \ diff --git a/parser2.cpp b/parser2.cpp index cbae3d2..77a2695 100644 --- a/parser2.cpp +++ b/parser2.cpp @@ -2,8 +2,11 @@ #include -// todo: field types -// todo: void() types +// fixme: register typedef'd types. this wouldn't matter if parameters required names +// defeated by a mere for (i = 0; i < n; ++i) +// `for\s*\(\s*([^\s]+)\s*=` -> `for (auto $1 =` +// fixme: GenericCommand_rpn -- operators in strings??? specifically "="?? +// fixme: HUD_ItemsTime // todo: template traits for each rule to enable prediction instead of backtracking // todo: commit to a rule if possible and disable backtracking // todo: store memo on heap @@ -208,11 +211,11 @@ Result opt(ctx_t &ctx) { } /// rule+ -#define CROSS(rule) ([&](ctx_t &) { \ - TRY(rule(ctx)); \ +#define CROSS(...) ([&](ctx_t &) { \ + TRY(__VA_ARGS__(ctx)); \ for (;;) { \ auto memo = ctx.memo(); \ - if (!rule(ctx)) { \ + if (!__VA_ARGS__(ctx)) { \ ctx.memo(memo); \ break; \ } \ @@ -227,7 +230,7 @@ Result cross(ctx_t &ctx) { } /// rule* == (rule+)? -#define STAR(rule) OPT(CROSS(rule)) +#define STAR(...) OPT(CROSS(__VA_ARGS__)) /// rule* == (rule+)? template @@ -238,7 +241,9 @@ Result star(ctx_t &ctx) { /// rule (s rule)* template Result sep(ctx_t &ctx) { - return seq>>(ctx); + TRY(rule(ctx)); + TRY(STAR(seq)(ctx)); + OK(); } /// rule[0] | rule[1..n] @@ -286,6 +291,39 @@ Result leftop(ctx_t &ctx) { struct grammar { + static constexpr auto Void = lit; + static constexpr auto Char = lit; + static constexpr auto Int = lit; + static constexpr auto Float = lit; + static constexpr auto Vector = lit; + static constexpr auto String = lit; + static constexpr auto Entity = lit; + + static constexpr auto Enum = lit; + static constexpr auto Typedef = lit; + + static constexpr auto Const = lit; + static constexpr auto Extern = lit; + static constexpr auto Static = lit; + static constexpr auto Noref = lit; + static constexpr auto Local = lit; + static constexpr auto Var = lit; + + static constexpr auto If = lit; + static constexpr auto Else = lit; + static constexpr auto Switch = lit; + static constexpr auto Case = lit; + static constexpr auto Default = lit; + + static constexpr auto While = lit; + static constexpr auto Do = lit; + static constexpr auto For = lit; + + static constexpr auto Goto = lit; + static constexpr auto Continue = lit; + static constexpr auto Break = lit; + static constexpr auto Return = lit; + // declarations /// : translationUnit? EOF @@ -304,12 +342,14 @@ struct grammar { /// : pragma /// | functionDefinition /// | declaration + /// | enumDeclaration /// | ';' RULE(externalDeclaration) { TRY(alt< pragma, functionDefinition, declaration, + enumDeclaration, tok >(ctx)); OK(); @@ -328,124 +368,96 @@ struct grammar { } /// : declarationSpecifiers? declarator compoundStatement + /// | declarationSpecifiers? declarator '=' compoundStatement # legacy RULE(functionDefinition) { TRY(OPT(declarationSpecifiers)(ctx)); TRY(declarator(ctx)); + TRY(OPT(tok)(ctx)); // legacy TRY(compoundStatement(ctx)); OK(); } - /// : declarationSpecifier+ + /// : attribute* (storageClassSpecifier | typeQualifier)* typeSpecifier RULE(declarationSpecifiers) { - TRY(CROSS(declarationSpecifier)(ctx)); + TRY(STAR(attribute)(ctx)); + TRY(STAR(alt)(ctx)); + TRY(typeSpecifier(ctx)); OK(); } - /// : storageClassSpecifier - /// | typeSpecifier - /// | typeQualifier - /// | functionSpecifier - RULE(declarationSpecifier) { - TRY(alt< - storageClassSpecifier, - typeSpecifier, - typeQualifier, - functionSpecifier - >(ctx)); + + /// : '[[' X ']]' + RULE(attribute) { + EXPECT(Token::ATTRIBUTE_OPEN); + if (ACCEPT_IDENT("alias")) { + EXPECT(Token::PAREN_OPEN); + TRY(CROSS(tok)(ctx)); + EXPECT(Token::PAREN_CLOSE); + } else if (ACCEPT_IDENT("eraseable")) { + } else if (ACCEPT_IDENT("accumulate")) { + } else { + ERR("unknown attribute '" + STRING() + "'"); + } + EXPECT(Token::ATTRIBUTE_CLOSE); OK(); } /// : 'typedef' /// | 'extern' /// | 'static' + /// | 'noref' + /// | 'local' # legacy + /// | 'var' # legacy RULE(storageClassSpecifier) { - constexpr auto Typedef = lit; - constexpr auto Extern = lit; - constexpr auto Static = lit; - TRY(alt< Typedef, Extern, - Static + Static, + Noref, + Local, + Var >(ctx)); OK(); } - /// : ('void' | 'char' | 'int' | 'float' | 'entity') - /// | enumSpecifier - /// | typedefName + /// : ('.' | '...')* directTypeSpecifier ('(' parameterTypeList ')')? RULE(typeSpecifier) { - constexpr auto Void = lit; - constexpr auto Char = lit; - constexpr auto Int = lit; - constexpr auto Float = lit; - constexpr auto Entity = lit; + TRY(STAR(alt, tok>)(ctx)); + TRY(directTypeSpecifier(ctx)); + TRY(OPT(seq, opt, tok>)(ctx)); + OK(); + } + /// : ('void' | 'char' | 'int' | 'float' | 'vector' | 'string' | 'entity') + /// | typedefName + RULE(directTypeSpecifier) { TRY(alt< alt< Void, Char, Int, Float, + Vector, + String, Entity >, - enumSpecifier, typedefName >(ctx)); OK(); } - /// : 'enum' '{' enumeratorList ','? '}' - RULE(enumSpecifier) { - constexpr auto Enum = lit; - - TRY(Enum(ctx)); - TRY(tok(ctx)); - TRY(enumeratorList(ctx)); - TRY(OPT(tok)(ctx)); - TRY(tok(ctx)); - OK(); - } - - /// : enumerator (',' enumerator)* - RULE(enumeratorList) { - TRY(sep>(ctx)); - OK(); - } - - /// : enumerationConstant ('=' constantExpression)? - RULE(enumerator) { - TRY(enumerationConstant(ctx)); - TRY(OPT(seq, constantExpression>)(ctx)); - OK(); - } - - /// : Identifier - RULE(enumerationConstant) { - TRY(tok(ctx)); - OK(); - } - /// : Identifier RULE(typedefName) { - TRY(tok(ctx)); + TRY(tok(ctx)); OK(); } /// : 'const' RULE(typeQualifier) { - constexpr auto Const = lit; - TRY(Const(ctx)); OK(); } - /// : '[[' .+ ']]' - /// todo - RULE(functionSpecifier) { - BT(); - } - /// : Identifier ( /// '[' assignmentExpression_15? ']' /// | '(' parameterTypeList? ')' @@ -464,38 +476,37 @@ struct grammar { /// | '(' parameterTypeList? ')' /// )+ RULE(abstractDeclarator) { - TRY(star, opt, tok>, seq, opt, tok> >>(ctx)); OK(); } - /// : parameterList (',' parameterVarargs)? - /// | parameterVarargs + /// : (parameterVarargDeclaration | parameterDeclaration) (',' (parameterVarargDeclaration | parameterDeclaration))* RULE(parameterTypeList) { - TRY(opt, tok>>>, - tok - >>(ctx)); - OK(); - } - - /// : parameterDeclaration (',' parameterDeclaration)* - RULE(parameterList) { - TRY(sep>(ctx)); + TRY(sep, tok>(ctx)); OK(); } /// : declarationSpecifiers (declarator | abstractDeclarator?) RULE(parameterDeclaration) { - TRY(seq> + opt >(ctx)); OK(); } + /// : declarationSpecifiers? '...' Identifier? + RULE(parameterVarargDeclaration) { + TRY(OPT(declarationSpecifiers)(ctx)); + TRY(tok(ctx)); + TRY(OPT(tok)(ctx)); + OK(); + } + /// : declarationSpecifiers initDeclaratorList? ';' RULE(declaration) { TRY(declarationSpecifiers(ctx)); @@ -532,6 +543,35 @@ struct grammar { OK(); } + /// : 'enum' '{' enumeratorList ','? '}' + RULE(enumDeclaration) { + TRY(Enum(ctx)); + TRY(tok(ctx)); + TRY(enumeratorList(ctx)); + TRY(OPT(tok)(ctx)); + TRY(tok(ctx)); + OK(); + } + + /// : enumerator (',' enumerator)* + RULE(enumeratorList) { + TRY(sep>(ctx)); + OK(); + } + + /// : enumerationConstant ('=' constantExpression)? + RULE(enumerator) { + TRY(enumerationConstant(ctx)); + TRY(OPT(seq, constantExpression>)(ctx)); + OK(); + } + + /// : Identifier + RULE(enumerationConstant) { + TRY(tok(ctx)); + OK(); + } + // statements /// : labeledStatement @@ -553,19 +593,21 @@ struct grammar { } /// : ( - /// Identifier - /// | 'case' constantExpression + /// 'case' constantExpression /// | 'default' + /// | Identifier /// ) ':' statement + /// | ':' Identifier # legacy RULE(labeledStatement) { - constexpr auto Case = lit; - constexpr auto Default = lit; - - TRY(seq, - seq, - Default - >, tok, statement>(ctx)); + constexpr auto legacy = seq, tok>; + TRY(alt< + seq, + Default, + tok + >, tok, alt>, // declarations are an extension + legacy + >(ctx)); OK(); } @@ -594,10 +636,6 @@ struct grammar { /// : 'if' '(' expression ')' statement ('else' statement)? /// | 'switch' '(' expression ')' statement RULE(selectionStatement) { - constexpr auto If = lit; - constexpr auto Else = lit; - constexpr auto Switch = lit; - TRY(alt< seq, expression, tok, statement, opt>>, seq, expression, tok, statement> @@ -609,10 +647,6 @@ struct grammar { /// | 'do' statement 'while' '(' expression ')' ';' /// | 'for' '(' forCondition ')' statement RULE(iterationStatement) { - constexpr auto While = lit; - constexpr auto Do = lit; - constexpr auto For = lit; - TRY(alt< seq, expression, tok, statement>, seq, expression, tok, tok>, @@ -621,7 +655,7 @@ struct grammar { OK(); } - /// : (forDeclaration | expression)? ';' forExpression? ';' forExpression? + /// : (expression | forDeclaration)? ';' forExpression? ';' forExpression? RULE(forCondition) { /// : declarationSpecifiers initDeclaratorList? constexpr auto forDeclaration = seq>; @@ -639,11 +673,6 @@ struct grammar { /// | 'break' ';' /// | 'return' expression? ';' RULE(jumpStatement) { - constexpr auto Goto = lit; - constexpr auto Continue = lit; - constexpr auto Break = lit; - constexpr auto Return = lit; - TRY(alt< seq, tok>, seq>, @@ -685,25 +714,25 @@ struct grammar { tok, tok, tok, - seq, tok>, - seq, tok>, + tok, + tok, tok, tok, tok >, tok> >; TRY(alt< - seq, + seq, assignmentOperator, assignmentExpression_15>, conditionalExpression >(ctx)); OK(); } - /// : logicalOrExpression_14 ('?' expression ':' conditionalExpression)? + /// : logicalOrExpression_14 ('?' expression ':' expression)? /// right associative RULE(conditionalExpression) { TRY(logicalOrExpression_14(ctx)); - TRY(OPT(seq, expression, tok, conditionalExpression>)(ctx)); + TRY(OPT(seq, expression, tok, expression>)(ctx)); OK(); } @@ -720,7 +749,7 @@ struct grammar { RULE(logicalAndExpression_13) { TRY(leftop< inclusiveOrExpression_12, - seq, tok> + tok >(ctx)); OK(); } @@ -769,8 +798,10 @@ struct grammar { TRY(leftop< shiftExpression_7, alt< - seq, opt>>, - seq, opt>> + tok, + tok, + tok, + tok > >(ctx)); OK(); @@ -781,8 +812,8 @@ struct grammar { TRY(leftop< additiveExpression_6, alt< - seq, tok>, - seq, tok> + tok, + tok > >(ctx)); OK(); @@ -800,14 +831,15 @@ struct grammar { OK(); } - /// : castExpression_3 (('*' | '/' | '%') castExpression_3)* + /// : castExpression_3 (('*' | '/' | '%' | '><') castExpression_3)* RULE(multiplicativeExpression_5) { TRY(leftop< castExpression_3, alt< tok, tok, - tok + tok, + tok > >(ctx)); OK(); @@ -821,13 +853,13 @@ struct grammar { return unaryExpression_3(ctx); } - /// : postfixExpression_2 + /// : postfixExpression_2 ('**' unaryExpression_3)* /// | ('++' | '--') unaryExpression_3 /// | ('+' | '-' | '~' | '!') castExpression_3 /// right associative RULE(unaryExpression_3) { TRY(alt< - postfixExpression_2, + seq, tok, unaryExpression_3>>>, seq, tok>, seq, tok> @@ -867,7 +899,7 @@ struct grammar { /// : Identifier /// | Constant /// | StringLiteral+ - /// | '...' '(' expression ',' typeSpecifier ')' # absolute va_arg + /// | '...' '(' assignmentExpression_15 ',' typeSpecifier ')' # absolute va_arg /// | '(' expression ')' RULE(primaryExpression) { TRY(alt< @@ -877,7 +909,8 @@ struct grammar { tok, tok, cross>, - seq, tok, expression, tok, typeSpecifier, tok>, + seq, tok>, + seq, tok, assignmentExpression_15, tok, typeSpecifier, tok>, seq, expression, tok> >(ctx)); OK();