yyextra->no_.AtImplementation = false; \
@end
yyextra->no_.Function = false; \
+ yyextra->no_.NewLine = false; \
yyextra->no_.OpenBrace = false; \
yylval->highlight_ = highlight; \
return token; \
#define Y P.strmemdup(yytext, yyleng)
#define I(type, Type, value, highlight) do { \
- yylval->type ## _ = A CY ## Type; \
+ yylval->semantic_.type ## _ = A CY ## Type; \
F(value, highlight); \
} while (false)
-#define T yylval->newline_ = yyextra->state_ == CYNewLine; BEGIN(Div);
-#define C T yyextra->state_ = CYClear;
-#define R T yyextra->state_ = CYRestricted;
+#define C \
+ yyextra->newline_ = yyextra->last_; \
+ yyextra->last_ = false; \
+ BEGIN(Div);
#define N \
- if (yyextra->state_ != CYNewLine) { \
- if (yyextra->state_ != CYRestricted) \
- yyextra->state_ = CYNewLine; \
- else { \
- yyextra->state_ = CYClear; \
- F(tk::NewLine, hi::Nothing); \
- } \
- }
+ yyextra->last_ = true; \
+ if (yyextra->no_.NewLine) \
+ F(tk::NewLine, hi::Nothing);
#define V(more) { \
if (const char *nl = reinterpret_cast<const char *>(memchr(yytext, '\n', yyleng))) { \
"=" L C F(tk::Equal, hi::Operator);
"==" L C F(tk::EqualEqual, hi::Operator);
"===" L C F(tk::EqualEqualEqual, hi::Operator);
-"=>" L C F(yylval->newline_ ? tk::EqualRight_ : tk::EqualRight, hi::Operator);
+"=>" L C F(yyextra->newline_ ? tk::EqualRight_ : tk::EqualRight, hi::Operator);
"!" L C F(tk::Exclamation, hi::Operator);
"!=" L C F(tk::ExclamationEqual, hi::Operator);
"!==" L C F(tk::ExclamationEqualEqual, hi::Operator);
"-" L C F(tk::Hyphen, hi::Operator);
"-=" L C F(tk::HyphenEqual, hi::Operator);
-"--" L C F(yylval->newline_ ? tk::HyphenHyphen_ : tk::HyphenHyphen, hi::Operator);
+"--" L C F(yyextra->newline_ ? tk::HyphenHyphen_ : tk::HyphenHyphen, hi::Operator);
"->" L C F(tk::HyphenRight, hi::Operator);
"<" L C F(tk::Left, hi::Operator);
"<=" L C F(tk::LeftEqual, hi::Operator);
"||" L C F(tk::PipePipe, hi::Operator);
"+" L C F(tk::Plus, hi::Operator);
"+=" L C F(tk::PlusEqual, hi::Operator);
-"++" L C F(yylval->newline_ ? tk::PlusPlus_ : tk::PlusPlus, hi::Operator);
+"++" L C F(yyextra->newline_ ? tk::PlusPlus_ : tk::PlusPlus, hi::Operator);
">" L C F(tk::Right, hi::Operator);
">=" L C F(tk::RightEqual, hi::Operator);
">>" L C F(tk::RightRight, hi::Operator);
"(" L C F(tk::OpenParen, hi::Structure);
")" L C F(tk::CloseParen, hi::Structure);
-"{" L C F(yyextra->no_.OpenBrace ? tk::OpenBrace__ : yylval->newline_ ? tk::OpenBrace_ : tk::OpenBrace, hi::Structure);
+"{" L C F(yyextra->no_.OpenBrace ? tk::OpenBrace__ : yyextra->newline_ ? tk::OpenBrace_ : tk::OpenBrace, hi::Structure);
"}" L C F(tk::CloseBrace, hi::Structure);
"[" L C F(tk::OpenBracket, hi::Structure);
"abstract" L C /*FII*/ F(tk::_abstract_, hi::Meta);
"await" L C /*II?*/ F(tk::_await_, hi::Meta);
"boolean" L C /*FII*/ F(tk::_boolean_, hi::Type);
-"break" L R /*KKK*/ F(tk::_break_, hi::Control);
+"break" L C /*KKK*/ F(tk::_break_, hi::Control);
"byte" L C /*FII*/ F(tk::_byte_, hi::Type);
"case" L C /*KKK*/ F(tk::_case_, hi::Control);
"catch" L C /*KKK*/ F(tk::_catch_, hi::Control);
"char" L C /*FII*/ F(tk::_char_, hi::Type);
"class" L C /*FFK*/ F(tk::_class_, hi::Meta);
"const" L C /*FFK*/ F(tk::_const_, hi::Meta);
-"continue" L R /*KKK*/ F(tk::_continue_, hi::Control);
+"continue" L C /*KKK*/ F(tk::_continue_, hi::Control);
"debugger" L C /*FKK*/ F(tk::_debugger_, hi::Meta);
"default" L C /*KKK*/ F(tk::_default_, hi::Control);
"delete" L C /*KKK*/ F(tk::_delete_, hi::Operator);
"private" L C /*FSS*/ F(tk::_private_, hi::Meta);
"protected" L C /*FSS*/ F(tk::_protected_, hi::Meta);
"public" L C /*FSS*/ F(tk::_public_, hi::Meta);
-"return" L R /*KKK*/ F(tk::_return_, hi::Control);
+"return" L C /*KKK*/ F(tk::_return_, hi::Control);
"short" L C /*FII*/ F(tk::_short_, hi::Type);
"static" L C /*FS?*/ F(tk::_static_, hi::Meta);
"super" L C /*FFK*/ F(tk::_super_, hi::Constant);
"switch" L C /*KKK*/ F(tk::_switch_, hi::Control);
"synchronized" L C /*FII*/ F(tk::_synchronized_, hi::Meta);
"this" L C /*KKK*/ F(tk::_this_, hi::Constant);
-"throw" L R /*KKK*/ F(tk::_throw_, hi::Control);
+"throw" L C /*KKK*/ F(tk::_throw_, hi::Control);
"throws" L C /*FII*/ F(tk::_throws_, hi::Meta);
"transient" L C /*FII*/ F(tk::_transient_, hi::Meta);
"true" L C /*LLL*/ F(tk::_true_, hi::Constant);
"volatile" L C /*FII*/ F(tk::_volatile_, hi::Meta);
"while" L C /*KKK*/ F(tk::_while_, hi::Control);
"with" L C /*KKK*/ F(tk::_with_, hi::Control);
-"yield" L R /*IS?*/ F(tk::_yield_, hi::Control);
+"yield" L C /*IS?*/ F(tk::_yield_, hi::Control);
"auto" L C F(tk::_auto_, hi::Meta);
"each" L C F(tk::_each_, hi::Control);
@end
#include "Highlight.hpp"
+}
-typedef struct {
- bool newline_;
- hi::Value highlight_;
-
- union {
- bool bool_;
-
- CYArgument *argument_;
- CYAssignment *assignment_;
- CYBoolean *boolean_;
- CYClause *clause_;
- cy::Syntax::Catch *catch_;
- CYComment *comment_;
- CYComprehension *comprehension_;
- CYDeclaration *declaration_;
- CYDeclarations *declarations_;
- CYElement *element_;
- CYExpression *expression_;
- CYFalse *false_;
- CYFinally *finally_;
- CYForInitialiser *for_;
- CYForInInitialiser *forin_;
- CYFunctionParameter *functionParameter_;
- CYIdentifier *identifier_;
- CYInfix *infix_;
- CYLiteral *literal_;
- CYMember *member_;
- CYModule *module_;
- CYNull *null_;
- CYNumber *number_;
- CYParenthetical *parenthetical_;
- CYProgram *program_;
- CYProperty *property_;
- CYPropertyName *propertyName_;
- CYRubyProc *rubyProc_;
- CYStatement *statement_;
- CYString *string_;
- CYThis *this_;
- CYTrue *true_;
- CYWord *word_;
+%union { bool bool_; }
+
+%union { CYArgument *argument_; }
+%union { CYAssignment *assignment_; }
+%union { CYBoolean *boolean_; }
+%union { CYClause *clause_; }
+%union { cy::Syntax::Catch *catch_; }
+%union { CYComment *comment_; }
+%union { CYComprehension *comprehension_; }
+%union { CYDeclaration *declaration_; }
+%union { CYDeclarations *declarations_; }
+%union { CYElement *element_; }
+%union { CYExpression *expression_; }
+%union { CYFalse *false_; }
+%union { CYFinally *finally_; }
+%union { CYForInitialiser *for_; }
+%union { CYForInInitialiser *forin_; }
+%union { CYFunctionParameter *functionParameter_; }
+%union { CYIdentifier *identifier_; }
+%union { CYInfix *infix_; }
+%union { CYLiteral *literal_; }
+%union { CYMember *member_; }
+%union { CYModule *module_; }
+%union { CYNull *null_; }
+%union { CYNumber *number_; }
+%union { CYParenthetical *parenthetical_; }
+%union { CYProgram *program_; }
+%union { CYProperty *property_; }
+%union { CYPropertyName *propertyName_; }
+%union { CYRubyProc *rubyProc_; }
+%union { CYStatement *statement_; }
+%union { CYString *string_; }
+%union { CYThis *this_; }
+%union { CYTrue *true_; }
+%union { CYWord *word_; }
@begin C
- CYTypeModifier *modifier_;
- CYTypeSpecifier *specifier_;
- CYTypedIdentifier *typedIdentifier_;
- CYTypedParameter *typedParameter_;
+%union { CYTypeModifier *modifier_; }
+%union { CYTypeSpecifier *specifier_; }
+%union { CYTypedIdentifier *typedIdentifier_; }
+%union { CYTypedParameter *typedParameter_; }
@end
@begin ObjectiveC
- CYClassName *className_;
- CYClassField *classField_;
- CYMessage *message_;
- CYMessageParameter *messageParameter_;
- CYProtocol *protocol_;
- CYSelectorPart *selector_;
+%union { CYClassName *className_; }
+%union { CYClassField *classField_; }
+%union { CYMessage *message_; }
+%union { CYMessageParameter *messageParameter_; }
+%union { CYProtocol *protocol_; }
+%union { CYSelectorPart *selector_; }
@end
@begin E4X
- CYAttribute *attribute_;
- CYPropertyIdentifier *propertyIdentifier_;
- CYSelector *selector_;
+%union { CYAttribute *attribute_; }
+%union { CYPropertyIdentifier *propertyIdentifier_; }
+%union { CYSelector *selector_; }
@end
- };
-} YYSTYPE;
-
-#define YYSTYPE YYSTYPE
-}
%code provides {
+
+struct YYSTYPE {
+ cy::parser::semantic_type semantic_;
+ hi::Value highlight_;
+};
+
int cylex(YYSTYPE *, CYLocation *, void *);
+
+}
+
+%code {
+
+#undef yylex
+_finline int yylex(cy::parser::semantic_type *semantic, CYLocation *location, void *scanner) {
+ YYSTYPE data;
+ int token(cylex(&data, location, scanner));
+ *semantic = data.semantic_;
+ return token;
+}
+
}
%name-prefix "cy"
: { driver.SetCondition(CYDriver::RegExpCondition); }
;
+LexNoNewLine
+ : { if (!yyla.empty() && yyla.type_get() != yyeof_) error(@$, "unexpected lookahead"); driver.no_.NewLine = true; }
+ ;
+
LexNoBrace
: { if (yyla.empty()) driver.no_.OpenBrace = true; else if (yyla.type == yytranslate_(token::OpenBrace) || yyla.type == yytranslate_(token::OpenBrace_)) yyla.type = yytranslate_(token::OpenBrace__); }
;
: Word { $$ = $1; }
;
-NewLineOpt
- : "\n"
- |
- ;
-
Word
: Identifier { $$ = $1; }
| "auto" { $$ = CYNew CYWord("auto"); }
- | "break" NewLineOpt { $$ = CYNew CYWord("break"); }
+ | "break" { $$ = CYNew CYWord("break"); }
| "case" { $$ = CYNew CYWord("case"); }
| "catch" { $$ = CYNew CYWord("catch"); }
| "class" { $$ = CYNew CYWord("class"); }
| "const" { $$ = CYNew CYWord("const"); }
- | "continue" NewLineOpt { $$ = CYNew CYWord("continue"); }
+ | "continue" { $$ = CYNew CYWord("continue"); }
| "debugger" { $$ = CYNew CYWord("debugger"); }
| "default" { $$ = CYNew CYWord("default"); }
| "delete" LexSetRegExp { $$ = CYNew CYWord("delete"); }
| "new" LexSetRegExp { $$ = CYNew CYWord("new"); }
| "null" { $$ = CYNew CYWord("null"); }
- | "return" NewLineOpt { $$ = CYNew CYWord("return"); }
+ | "return" { $$ = CYNew CYWord("return"); }
| "super" { $$ = CYNew CYWord("super"); }
| "switch" { $$ = CYNew CYWord("switch"); }
| "this" { $$ = CYNew CYWord("this"); }
- | "throw" NewLineOpt { $$ = CYNew CYWord("throw"); }
+ | "throw" { $$ = CYNew CYWord("throw"); }
| "true" { $$ = CYNew CYWord("true"); }
| "try" { $$ = CYNew CYWord("try"); }
| "typeof" LexSetRegExp { $$ = CYNew CYWord("typeof"); }
// XXX: currently I only have this as Word
// | "let" { $$ = CYNew CYIdentifier("let"); }
- | "yield" NewLineOpt { $$ = CYNew CYIdentifier("yield"); }
+ | "yield" { $$ = CYNew CYIdentifier("yield"); }
| "each" { $$ = CYNew CYIdentifier("each"); }
| "of" { $$ = CYNew CYIdentifier("of"); }
: { driver.Warning(@$, "warning, automatic semi-colon insertion required"); }
;
+TerminatorSoft
+ : ";"
+ | "\n" StrictSemi
+ ;
+
Terminator
: ";"
- | error { if (yyla.type_get() != yyeof_ && yyla.type != yytranslate_(token::CloseBrace) && !yyla.value.newline_) { error(@1, "required semi-colon"); } else { yyerrok; driver.errors_.pop_back(); } } StrictSemi
+ | error { if (yyla.type_get() != yyeof_ && yyla.type != yytranslate_(token::CloseBrace) && !driver.newline_) { error(@1, "required semi-colon"); } else { yyerrok; driver.errors_.pop_back(); } } StrictSemi
;
TerminatorOpt
/* }}} */
/* 12.7 The continue Statement {{{ */
+Continue
+ : "continue" LexNoNewLine
+ ;
+
ContinueStatement
- : "continue" "\n" StrictSemi { $$ = CYNew CYContinue(NULL); }
- | "continue" IdentifierOpt Terminator { $$ = CYNew CYContinue($2); }
+ : Continue TerminatorSoft { $$ = CYNew CYContinue(NULL); }
+ | Continue Identifier Terminator { $$ = CYNew CYContinue($2); }
;
/* }}} */
/* 12.8 The break Statement {{{ */
+Break
+ : "break" LexNoNewLine
+ ;
+
BreakStatement
- : "break" "\n" StrictSemi { $$ = CYNew CYBreak(NULL); }
- | "break" IdentifierOpt Terminator { $$ = CYNew CYBreak($2); }
+ : Break TerminatorSoft { $$ = CYNew CYBreak(NULL); }
+ | Break Identifier Terminator { $$ = CYNew CYBreak($2); }
;
/* }}} */
/* 12.9 The return Statement {{{ */
+Return
+ : "return" LexNoNewLine
+ ;
+
ReturnStatement
- : "return" LexSetRegExp "\n" StrictSemi { $$ = CYNew CYReturn(NULL); }
- | "return" ExpressionOpt Terminator { $$ = CYNew CYReturn($2); }
+ : Return LexSetRegExp TerminatorSoft { $$ = CYNew CYReturn(NULL); }
+ | Return Expression Terminator { $$ = CYNew CYReturn($2); }
;
/* }}} */
/* 12.10 The with Statement {{{ */
;
/* }}} */
/* 12.13 The throw Statement {{{ */
+ThrowWord
+ : "throw" LexNoNewLine
+ ;
+
ThrowStatement
- : "throw" LexSetRegExp "\n" StrictSemi { error(@1, "throw without exception"); }
- | "throw" Expression Terminator { $$ = CYNew cy::Syntax::Throw($2); }
+ : ThrowWord LexSetRegExp TerminatorSoft { error(@1, "throw without exception"); }
+ | ThrowWord Expression Terminator { $$ = CYNew cy::Syntax::Throw($2); }
;
/* }}} */
/* 12.14 The try Statement {{{ */