/* * Copyright 2006-2012 Adrian Thurston * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to * deal in the Software without restriction, including without limitation the * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or * sell copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #include #include #include "config.h" #include "lmparse.h" #include "global.h" #include "input.h" using std::cout; using std::cerr; using std::endl; %%{ parser ColmParser; include "lmparse.kh"; start: root_item_list final { pd->rootCodeBlock = CodeBlock::cons( $1->stmtList, 0 ); }; nonterm root_item_list uses lang_stmt_list; root_item_list: root_item_list root_item final { $$->stmtList = appendStatement( $1->stmtList, $2->stmt ); }; root_item_list: final { $$->stmtList = new StmtList; }; nonterm root_item uses statement; root_item: literal_def commit final { $$->stmt = 0; }; root_item: rl_def commit final { $$->stmt = 0; }; root_item: token_def commit final { $$->stmt = 0; }; root_item: cfl_def commit final { $$->stmt = 0; }; root_item: region_def commit final { $$->stmt = 0; }; root_item: context_def commit final { $$->stmt = 0; }; root_item: namespace_def commit final { $$->stmt = 0; }; root_item: function_def commit final { $$->stmt = 0; }; root_item: iter_def commit final { $$->stmt = 0; }; root_item: global_def commit final { $$->stmt = $1->stmt; }; root_item: export_def commit final { $$->stmt = 0; }; root_item: statement commit final { $$->stmt = $1->stmt; }; root_item: pre_eof commit final { $$->stmt = 0; }; root_item: precedence commit final { $$->stmt = 0; }; root_item: typedef commit final { $$->stmt = 0; }; nonterm block_open { ObjectDef *localFrame; }; block_open: '{' final { $$->localFrame = blockOpen(); }; block_close: '}' final { blockClose(); }; iter_def: KW_Iter TK_Word '(' opt_param_list ')' block_open lang_stmt_list block_close final { iterDef( $7->stmtList, $6->localFrame, $4->paramList, $2->data ); }; function_def: type_ref TK_Word '(' opt_param_list ')' block_open lang_stmt_list block_close final { functionDef( $7->stmtList, $6->localFrame, $4->paramList, $1->typeRef, $2->data ); }; nonterm opt_param_list uses param_list; opt_param_list: param_list final { $$->paramList = $1->paramList; }; opt_param_list: final { $$->paramList = new ParameterList; }; nonterm param_list { ParameterList *paramList; }; param_list: param_list param_var_def final { $$->paramList = appendParam( $1->paramList, $2->objField ); }; param_list: param_var_def final { $$->paramList = appendParam( new ParameterList, $1->objField ); }; nonterm param_var_def uses var_def; param_var_def: TK_Word ':' type_ref final { $$->objField = addParam( $1->loc, $3->typeRef, $1->data ); }; param_var_def: TK_Word ':' reference_type_ref final { $$->objField = addParam( $1->loc, $3->typeRef, $1->data ); }; nonterm reference_type_ref uses type_ref; reference_type_ref: KW_Ref type_ref final { $$->typeRef = TypeRef::cons( $1->loc, TypeRef::Ref, $2->typeRef ); }; nonterm global_def uses statement; global_def: KW_Global var_def opt_def_init final { $$->stmt = globalDef( $2->objField, $3->expr, $3->assignType ); }; nonterm export_def uses statement; export_def: KW_Export var_def opt_def_init final { $$->stmt = exportStmt( $2->objField, $3->assignType, $3->expr ); }; precedence: pred_type pred_token_list final { precedenceStmt( $1->predType, $2->predDeclList ); }; nonterm pred_type { PredType predType; }; pred_type: KW_Left final { $$->predType = PredLeft; }; pred_type: KW_Right final { $$->predType = PredRight; }; pred_type: KW_Nonassoc final { $$->predType = PredNonassoc; }; nonterm pred_token_list { PredDeclList *predDeclList; }; pred_token_list: pred_token_list ',' pred_token final { $$->predDeclList = $1->predDeclList; $$->predDeclList->append( $3->predDecl ); }; pred_token_list: pred_token final { $$->predDeclList = new PredDeclList; $$->predDeclList->append( $1->predDecl ); }; nonterm pred_token { PredDecl *predDecl; }; pred_token: region_qual TK_Word final { $$->predDecl = predTokenName( $2->loc, $1->nspaceQual, $2->data ); }; pred_token: region_qual TK_Literal final { $$->predDecl = predTokenLit( $2->loc, $2->data, $1->nspaceQual ); }; typedef: KW_Alias TK_Word type_ref final { alias( $1->loc, $2->data, $3->typeRef ); }; cfl_def: cfl_def_head obj_var_list opt_reduce_first cfl_prod_list final { $2->objectDef->name = $1->name; NtDef *ntDef = NtDef::cons( $1->name, namespaceStack.top(), contextStack.top(), $3->reduceFirst ); cflDef( ntDef, $2->objectDef, $4->defList ); }; nonterm class cfl_def_head { String name; }; cfl_def_head: KW_Def TK_Word final { $$->name = $2->data; }; nonterm cfl_prod_list { LelDefList *defList; }; cfl_prod_list: cfl_prod_list '|' define_prod final { $$->defList = prodAppend( $1->defList, $3->definition ); }; cfl_prod_list: define_prod final { $$->defList = prodAppend( new LelDefList, $1->definition ); }; nonterm opt_reduce_first { bool reduceFirst; }; opt_reduce_first: KW_ReduceFirst final { $$->reduceFirst = true; }; opt_reduce_first: final { $$->reduceFirst = false; }; nonterm opt_prec { LangEl *predOf; }; opt_prec: final { $$->predOf = 0; }; opt_prec: KW_Prec pred_token final { //$$->predOf = $2->factor->langEl; assert(false); }; nonterm define_prod { Production *definition; }; define_prod: '[' prod_el_list ']' opt_commit opt_reduce_code opt_prec final { $$->definition = production( $1->loc, $2->list, $4->commit, $5->codeBlock, $6->predOf ); }; nonterm obj_var_list { ObjectDef *objectDef; }; obj_var_list: obj_var_list var_def final { objVarDef( $1->objectDef, $2->objField ); $$->objectDef = $1->objectDef; }; obj_var_list: final { $$->objectDef = ObjectDef::cons( ObjectDef::UserType, String(), pd->nextObjectId++ ); }; nonterm type_ref { TypeRef *typeRef; }; type_ref: basic_type_ref final { $$->typeRef = $1->typeRef; }; type_ref: KW_Map '<' type_ref type_ref '>' final { $$->typeRef = TypeRef::cons( $1->loc, TypeRef::Map, 0, $3->typeRef, $4->typeRef ); }; type_ref: KW_List '<' type_ref '>' final { $$->typeRef = TypeRef::cons( $1->loc, TypeRef::List, 0, $3->typeRef, 0 ); }; type_ref: KW_Vector '<' type_ref '>' final { $$->typeRef = TypeRef::cons( $1->loc, TypeRef::Vector, 0, $3->typeRef, 0 ); }; type_ref: KW_Parser '<' type_ref '>' final { $$->typeRef = TypeRef::cons( $1->loc, TypeRef::Parser, 0, $3->typeRef, 0 ); }; nonterm basic_type_ref uses type_ref; basic_type_ref: region_qual TK_Word opt_repeat final { $$->typeRef = TypeRef::cons( $2->loc, $1->nspaceQual, $2->data, $3->repeatType ); }; basic_type_ref: KW_Ptr region_qual TK_Word opt_repeat final { TypeRef *inner = TypeRef::cons( $1->loc, $2->nspaceQual, $3->data, $4->repeatType ); $$->typeRef = TypeRef::cons( $1->loc, TypeRef::Ptr, inner ); }; nonterm var_def { InputLoc loc; ObjectField *objField; }; var_def: TK_Word ':' type_ref final { /* Return an object field object. The user of this nonterminal must * load it into the approrpriate map and do error checking. */ $$->objField = ObjectField::cons( $1->loc, $3->typeRef, $1->data ); }; region_def: region_head root_item_list KW_End final { popRegionSet(); }; region_head: KW_Lex final { pushRegionSet( $1->loc ); }; namespace_def: namespace_head root_item_list KW_End final { namespaceStack.pop(); }; namespace_head: KW_Namespace TK_Word final { /* Make the new namespace. */ createNamespace( $1->loc, $2->data ); }; context_var_def: var_def final { contextVarDef( $1->loc, $1->objField ); }; context_item: context_var_def commit; context_item: literal_def commit; context_item: rl_def commit; context_item: token_def commit; context_item: cfl_def commit; context_item: region_def commit; context_item: context_def commit; context_item: function_def commit; context_item: iter_def commit; context_item: export_def commit; context_item: pre_eof commit; context_item: precedence commit; context_item_list: context_item_list context_item; context_item_list: ; context_def: context_head context_item_list KW_End final { contextStack.pop(); namespaceStack.pop(); }; context_head: KW_Context TK_Word final { contextHead( $1->loc, $2->data ); }; # # Pattern # nonterm pattern { PatternItemList *list; InputLoc loc; }; pattern: pattern_list final { $$->list = $1->list; }; nonterm pattern_list uses pattern; pattern_list: pattern_list pattern_top_el final { $$->list = patListConcat( $1->list, $2->list ); }; pattern_list: pattern_top_el final { $$->list = $1->list; }; nonterm pattern_top_el uses pattern; pattern_top_el: '"' litpat_el_list '"' final { $$->list = $2->list; }; pattern_top_el: '[' pattern_el_list ']' final { $$->list = $2->list; }; nonterm litpat_el_list uses pattern; litpat_el_list: litpat_el_list litpat_el final { $$->list = patListConcat( $1->list, $2->list ); }; litpat_el_list: final { $$->list = new PatternItemList; }; nonterm litpat_el uses pattern; litpat_el: TK_LitPat final { PatternItem *patternItem = PatternItem::cons( $1->loc, $1->data, PatternItem::InputText ); $$->list = PatternItemList::cons( patternItem ); }; litpat_el: '[' pattern_el_list ']' final { $$->list = $2->list; }; nonterm pattern_el_list uses pattern; pattern_el_list: pattern_el_list pattern_el final { $$->list = patListConcat( $1->list, $2->list ); }; pattern_el_list: final { $$->list = new PatternItemList; }; nonterm pattern_el uses pattern; pattern_el: opt_label pattern_el_type_or_lit final { $$->list = patternEl( $1->varRef, $2->list ); }; nonterm pattern_el uses pattern; pattern_el: '"' litpat_el_list '"' final { $$->list = $2->list; }; pattern_el: '?' TK_Word final { /* FIXME: Implement */ assert(false); }; nonterm pattern_el_type_or_lit uses pattern; pattern_el_type_or_lit: region_qual TK_Word opt_repeat final { $$->list = patternElNamed( $2->loc, $1->nspaceQual, $2->data, $3->repeatType ); }; pattern_el_type_or_lit: region_qual TK_Literal opt_repeat final { $$->list = patternElType( $2->loc, $1->nspaceQual, $2->data, $3->repeatType ); }; nonterm opt_label { /* Variable reference. */ LangVarRef *varRef; }; opt_label: TK_Word ':' final { $$->varRef = LangVarRef::cons( $1->loc, $1->data ); }; opt_label: final { $$->varRef = 0; }; # # Constructor List (constructor) # nonterm constructor { ConsItemList *list; }; constructor: cons_list final { $$->list = $1->list; }; nonterm cons_list uses constructor; cons_list: cons_top_el cons_list final { $$->list = consListConcat( $1->list, $2->list ); }; cons_list: cons_top_el final { $$->list = $1->list; }; nonterm cons_top_el uses constructor; cons_top_el: '"' lit_cons_el_list '"' final { $$->list = $2->list; }; cons_top_el: '[' cons_el_list ']' final { $$->list = $2->list; }; nonterm lit_cons_el_list uses constructor; lit_cons_el_list: lit_cons_el_list lit_cons_el final { $$->list = consListConcat( $1->list, $2->list ); }; lit_cons_el_list: final { $$->list = new ConsItemList; }; nonterm lit_cons_el uses constructor; lit_cons_el: TK_LitPat final { ConsItem *consItem = ConsItem::cons( $1->loc, ConsItem::InputText, $1->data ); $$->list = ConsItemList::cons( consItem ); }; lit_cons_el: '[' cons_el_list ']' final { $$->list = $2->list; }; nonterm cons_el_list uses constructor; cons_el_list: cons_el_list cons_el final { $$->list = consListConcat( $1->list, $2->list ); }; cons_el_list: final { $$->list = new ConsItemList; }; nonterm cons_el uses constructor; cons_el: region_qual TK_Literal final { $$->list = consElLiteral( $2->loc, $2->data, $1->nspaceQual ); }; cons_el: '"' lit_cons_el_list '"' final { $$->list = $2->list; }; cons_el: code_expr final { ConsItem *consItem = ConsItem::cons( $1->expr->loc, ConsItem::ExprType, $1->expr ); $$->list = ConsItemList::cons( consItem ); }; # # Accumulate List # nonterm accumulate { ConsItemList *list; }; accumulate: accum_list final { $$->list = $1->list; }; nonterm accum_list uses accumulate; accum_list: accum_top_el accum_list final { $$->list = consListConcat( $1->list, $2->list ); }; accum_list: accum_top_el final { $$->list = $1->list; }; nonterm accum_top_el uses accumulate; accum_top_el: '"' lit_accum_el_list '"' final { $$->list = $2->list; }; accum_top_el: '[' accum_el_list ']' final { $$->list = $2->list; }; nonterm lit_accum_el_list uses accumulate; lit_accum_el_list: lit_accum_el_list lit_accum_el final { $$->list = consListConcat( $1->list, $2->list ); }; lit_accum_el_list: final { $$->list = new ConsItemList; }; nonterm lit_accum_el uses accumulate; lit_accum_el: TK_LitPat final { ConsItem *consItem = ConsItem::cons( $1->loc, ConsItem::InputText, $1->data ); $$->list = ConsItemList::cons( consItem ); }; lit_accum_el: '[' accum_el_list ']' final { $$->list = $2->list; }; nonterm accum_el_list uses accumulate; accum_el_list: accum_el_list accum_el final { $$->list = consListConcat( $1->list, $2->list ); }; accum_el_list: final { $$->list = new ConsItemList; }; nonterm accum_el uses accumulate; accum_el: code_expr final { ConsItem *consItem = ConsItem::cons( $1->expr->loc, ConsItem::ExprType, $1->expr ); $$->list = ConsItemList::cons( consItem ); }; accum_el: '"' lit_accum_el_list '"' final { $$->list = $2->list; }; # # String List # nonterm string { ConsItemList *list; }; string: string_list final { $$->list = $1->list; }; nonterm string_list uses string; string_list: string_top_el string_list final { $$->list = consListConcat( $1->list, $2->list ); }; string_list: string_top_el final { $$->list = $1->list; }; nonterm string_top_el uses string; string_top_el: '"' lit_string_el_list '"' final { $$->list = $2->list; }; string_top_el: '[' string_el_list ']' final { $$->list = $2->list; }; nonterm lit_string_el_list uses string; lit_string_el_list: lit_string_el_list lit_string_el final { $$->list = consListConcat( $1->list, $2->list ); }; lit_string_el_list: final { $$->list = new ConsItemList; }; nonterm lit_string_el uses string; lit_string_el: TK_LitPat final { ConsItem *consItem = ConsItem::cons( $1->loc, ConsItem::InputText, $1->data ); $$->list = ConsItemList::cons( consItem ); }; lit_string_el: '[' string_el_list ']' final { $$->list = $2->list; }; nonterm string_el_list uses string; string_el_list: string_el_list string_el final { $$->list = consListConcat( $1->list, $2->list ); }; string_el_list: final { $$->list = new ConsItemList; }; nonterm string_el uses string; string_el: code_expr final { ConsItem *consItem = ConsItem::cons( $1->expr->loc, ConsItem::ExprType, $1->expr ); $$->list = ConsItemList::cons( consItem ); }; string_el: '"' lit_string_el_list '"' final { $$->list = $2->list; }; # # Production Lists. # nonterm prod_el_list { ProdElList *list; }; prod_el_list: prod_el_list prod_el final { $$->list = appendProdEl( $1->list, $2->prodEl ); }; prod_el_list: final { $$->list = new ProdElList; }; nonterm opt_no_ignore { bool noIgnore; }; opt_no_ignore: KW_Ni final { $$->noIgnore = true; }; opt_no_ignore: final { $$->noIgnore = false; }; nonterm prod_el { ProdEl *prodEl; }; prod_el: opt_capture opt_commit region_qual TK_Word opt_repeat final { $$->prodEl = prodElName( $4->loc, $4->data, $3->nspaceQual, $1->objField, $5->repeatType, $2->commit ); }; prod_el: opt_capture opt_commit region_qual TK_Literal opt_repeat final { $$->prodEl = prodElLiteral( $4->loc, $4->data, $3->nspaceQual, $1->objField, $5->repeatType, $2->commit ); }; nonterm opt_repeat { bool opt; bool repeat; RepeatType repeatType; }; opt_repeat: '*' final { $$->opt = false; $$->repeat = true; $$->repeatType = RepeatRepeat; }; opt_repeat: '+' final { $$->opt = false; $$->repeat = false; $$->repeatType = RepeatList; }; opt_repeat: '?' final { $$->opt = true; $$->repeat = false; $$->repeatType = RepeatOpt; }; opt_repeat: final { $$->opt = false; $$->repeat = false; $$->repeatType = RepeatNone; }; nonterm region_qual { NamespaceQual *nspaceQual; }; region_qual: region_qual TK_Word TK_DoubleColon final { $$->nspaceQual = $1->nspaceQual; $$->nspaceQual->qualNames.append( $2->data ); }; region_qual: final { $$->nspaceQual = NamespaceQual::cons( namespaceStack.top() ); }; literal_def: KW_Literal literal_list; literal_list: literal_list ',' literal_item; literal_list: literal_item; literal_item: opt_no_ignore TK_Literal opt_no_ignore final { if ( strcmp( $2->data, "''" ) == 0 ) zeroDef( $2->loc, $2->data, $1->noIgnore, $3->noIgnore ); else literalDef( $2->loc, $2->data, $1->noIgnore, $3->noIgnore ); }; # These two productions are responsible for setting and unsetting the Regular # language scanning context. enter_rl: try { enterRl = true; } undo { enterRl = false; }; leave_rl: try { enterRl = false; } undo { enterRl = true; }; token_def: token_or_ignore token_def_name obj_var_list enter_rl opt_no_ignore '/' opt_lex_join leave_rl '/' opt_no_ignore opt_translate final { $3->objectDef->name = $2->name; defineToken( $1->loc, $2->name, $7->join, $3->objectDef, $11->transBlock, $1->ignore, $5->noIgnore, $10->noIgnore ); }; nonterm token_or_ignore { InputLoc loc; bool ignore; }; token_or_ignore: KW_Token final { $$->loc = $1->loc; $$->ignore = false; }; token_or_ignore: KW_Ignore final { $$->loc = $1->loc; $$->ignore = true; }; nonterm class token_def_name { String name; }; token_def_name: opt_name final { $$->name = $1->name; }; nonterm class opt_name { String name; }; opt_name: TK_Word final { $$->name = $1->data; }; opt_name: ; nonterm opt_translate { CodeBlock *transBlock; }; opt_translate: block_open lang_stmt_list block_close final { $$->transBlock = CodeBlock::cons( $2->stmtList, $1->localFrame ); $$->transBlock->context = contextStack.top(); }; opt_translate: final { $$->transBlock = 0; }; pre_eof: KW_Preeof block_open lang_stmt_list block_close final { preEof( $1->loc, $3->stmtList, $2->localFrame ); }; rl_def: KW_Rl machine_name enter_rl '/' lex_join leave_rl '/' final { /* Generic creation of machine for instantiation and assignment. */ addRegularDef( $2->loc, namespaceStack.top(), $2->data, $5->join ); }; type class token_data { InputLoc loc; String data; }; nonterm machine_name uses token_data; machine_name: TK_Word final { $$->loc = $1->loc; $$->data = $1->data; }; # # Reduce statements # nonterm opt_reduce_code { CodeBlock *codeBlock; }; opt_reduce_code: final { $$->codeBlock = 0; }; opt_reduce_code: start_reduce lang_stmt_list block_close final { $$->codeBlock = CodeBlock::cons( $2->stmtList, $1->localFrame ); $$->codeBlock->context = contextStack.top(); }; nonterm start_reduce uses block_open; start_reduce: block_open final { $$->localFrame = $1->localFrame; }; nonterm lang_stmt_list { StmtList *stmtList; }; lang_stmt_list: rec_stmt_list opt_require_stmt final { $$->stmtList = $1->stmtList; if ( $2->stmt != 0 ) $$->stmtList->append( $2->stmt ); }; nonterm rec_stmt_list uses lang_stmt_list; rec_stmt_list: rec_stmt_list statement final { $$->stmtList = $1->stmtList; /* Maybe a statement was generated. */ if ( $2->stmt != 0 ) $$->stmtList->append( $2->stmt ); }; rec_stmt_list: final { $$->stmtList = new StmtList; }; nonterm opt_def_init { LangExpr *expr; LangStmt::Type assignType; }; opt_def_init: '=' code_expr final { $$->expr = $2->expr; $$->assignType = LangStmt::AssignType; }; opt_def_init: final { $$->expr = 0; }; scope_push: final { pd->curLocalFrame->pushScope(); }; scope_pop: final { pd->curLocalFrame->popScope(); }; nonterm statement { LangStmt *stmt; }; nonterm for_scope uses statement; statement: var_def opt_def_init final { $$->stmt = varDef( $1->objField, $2->expr, $2->assignType ); }; statement: var_ref '=' code_expr final { $$->stmt = LangStmt::cons( $2->loc, LangStmt::AssignType, $1->varRef, $3->expr ); }; statement: KW_Print '(' code_expr_list ')' final { $$->stmt = LangStmt::cons( $1->loc, LangStmt::PrintType, $3->exprVect ); }; statement: KW_PrintXMLAC '(' code_expr_list ')' final { $$->stmt = LangStmt::cons( $1->loc, LangStmt::PrintXMLACType, $3->exprVect ); }; statement: KW_PrintXML '(' code_expr_list ')' final { $$->stmt = LangStmt::cons( $1->loc, LangStmt::PrintXMLType, $3->exprVect ); }; statement: KW_PrintStream '(' code_expr_list ')' final { $$->stmt = LangStmt::cons( $1->loc, LangStmt::PrintStreamType, $3->exprVect ); }; statement: code_expr final { $$->stmt = LangStmt::cons( InputLoc(), LangStmt::ExprType, $1->expr ); }; statement: if_stmt final { $$->stmt = $1->stmt; }; statement: KW_Reject final { $$->stmt = LangStmt::cons( $1->loc, LangStmt::RejectType ); }; statement: KW_While scope_push code_expr block_or_single scope_pop final { $$->stmt = LangStmt::cons( LangStmt::WhileType, $3->expr, $4->stmtList ); }; for_scope: TK_Word ':' type_ref KW_In iter_call block_or_single final { $$->stmt = forScope( $1->loc, $1->data, $3->typeRef, $5->langTerm, $6->stmtList ); }; statement: KW_For scope_push for_scope scope_pop final { $$->stmt = $3->stmt; }; statement: KW_Return code_expr final { $$->stmt = LangStmt::cons( $1->loc, LangStmt::ReturnType, $2->expr ); }; statement: KW_Break final { $$->stmt = LangStmt::cons( LangStmt::BreakType ); }; statement: KW_Yield var_ref final { $$->stmt = LangStmt::cons( LangStmt::YieldType, $2->varRef ); }; nonterm opt_require_stmt uses statement; opt_require_stmt: scope_push require_pattern lang_stmt_list scope_pop final { $$->stmt = LangStmt::cons( LangStmt::IfType, $2->expr, $3->stmtList, 0 ); }; opt_require_stmt: final { $$->stmt = 0; }; nonterm require_pattern uses code_expr; require_pattern: KW_Require var_ref pattern final { $$->expr = require( $1->loc, $2->varRef, $3->list ); }; nonterm block_or_single uses lang_stmt_list; block_or_single: '{' lang_stmt_list '}' final { $$->stmtList = $2->stmtList; }; block_or_single: statement final { $$->stmtList = new StmtList; $$->stmtList->append( $1->stmt ); }; nonterm iter_call { LangTerm *langTerm; }; iter_call: var_ref '(' opt_code_expr_list ')' final { $$->langTerm = LangTerm::cons( InputLoc(), $1->varRef, $3->exprVect ); }; iter_call: TK_Word final { $$->langTerm = LangTerm::cons( InputLoc(), LangTerm::VarRefType, LangVarRef::cons( $1->loc, $1->data ) ); }; # # If Statements # nonterm if_stmt uses statement; if_stmt: KW_If scope_push code_expr block_or_single scope_pop elsif_list final { $$->stmt = LangStmt::cons( LangStmt::IfType, $3->expr, $4->stmtList, $6->stmt ); }; nonterm elsif_list { LangStmt *stmt; }; elsif_list: elsif_clause elsif_list final { /* Put any of the followng elseif part, an else, or null into the elsePart. */ $$->stmt = $1->stmt; $$->stmt->elsePart = $2->stmt; }; elsif_list: optional_else final { $$->stmt = $1->stmt; }; nonterm elsif_clause { LangStmt *stmt; }; elsif_clause: KW_Elsif scope_push code_expr block_or_single scope_pop final { $$->stmt = LangStmt::cons( LangStmt::IfType, $3->expr, $4->stmtList, 0 ); }; nonterm optional_else { LangStmt *stmt; }; optional_else: KW_Else scope_push block_or_single scope_pop final { $$->stmt = LangStmt::cons( LangStmt::ElseType, $3->stmtList ); }; optional_else: final { $$->stmt = 0; }; # # Code LexExpression Lists. # nonterm code_expr_list { ExprVect *exprVect; }; code_expr_list: code_expr_list code_expr final { $$->exprVect = $1->exprVect; $$->exprVect->append( $2->expr ); }; code_expr_list: code_expr final { $$->exprVect = new ExprVect; $$->exprVect->append( $1->expr ); }; nonterm opt_code_expr_list uses code_expr_list; opt_code_expr_list: code_expr_list final { $$->exprVect = $1->exprVect; }; opt_code_expr_list: final { $$->exprVect = 0; }; # # Type list # nonterm type_list { TypeRefVect *typeRefVect; }; type_list: type_list ',' type_ref final { $$->typeRefVect = $1->typeRefVect; $$->typeRefVect->append( $3->typeRef ); }; type_list: type_ref final { $$->typeRefVect = new TypeRefVect; $$->typeRefVect->append( $1->typeRef ); }; nonterm opt_type_list uses type_list; opt_type_list: type_list final { $$->typeRefVect = $1->typeRefVect; }; opt_type_list: final { $$->typeRefVect = 0; }; # # Variable reference # nonterm var_ref { LangVarRef *varRef; }; var_ref: qual TK_Word final { $$->varRef = LangVarRef::cons( $2->loc, $1->qual, $2->data ); }; nonterm qual { QualItemVect *qual; }; qual: qual TK_Word '.' final { $$->qual = $1->qual; $$->qual->append( QualItem( $2->loc, $2->data, QualItem::Dot ) ); }; qual: qual TK_Word TK_RightArrow final { $$->qual = $1->qual; $$->qual->append( QualItem( $2->loc, $2->data, QualItem::Arrow ) ); }; qual: final { $$->qual = new QualItemVect; }; # # Code expression # nonterm code_expr { LangExpr *expr; }; code_expr: code_expr TK_AmpAmp code_relational final { $$->expr = LangExpr::cons( $2->loc, $1->expr, OP_LogicalAnd, $3->expr ); }; code_expr: code_expr TK_BarBar code_relational final { $$->expr = LangExpr::cons( $2->loc, $1->expr, OP_LogicalOr, $3->expr ); }; code_expr: code_relational final { $$->expr = $1->expr; }; nonterm code_relational uses code_expr; code_relational: code_relational TK_DoubleEql code_additive final { $$->expr = LangExpr::cons( $2->loc, $1->expr, OP_DoubleEql, $3->expr ); }; code_relational: code_relational TK_NotEql code_additive final { $$->expr = LangExpr::cons( $2->loc, $1->expr, OP_NotEql, $3->expr ); }; code_relational: code_relational '<' code_additive final { $$->expr = LangExpr::cons( $2->loc, $1->expr, '<', $3->expr ); }; code_relational: code_relational '>' code_additive final { $$->expr = LangExpr::cons( $2->loc, $1->expr, '>', $3->expr ); }; code_relational: code_relational TK_LessEql code_additive final { $$->expr = LangExpr::cons( $2->loc, $1->expr, OP_LessEql, $3->expr ); }; code_relational: code_relational TK_GrtrEql code_additive final { $$->expr = LangExpr::cons( $2->loc, $1->expr, OP_GrtrEql, $3->expr ); }; code_relational: code_additive final { $$->expr = $1->expr; }; nonterm code_additive uses code_expr; code_additive: code_additive '+' code_multiplicitive final { $$->expr = LangExpr::cons( $2->loc, $1->expr, '+', $3->expr ); }; code_additive: code_additive '-' code_multiplicitive final { $$->expr = LangExpr::cons( $2->loc, $1->expr, '-', $3->expr ); }; code_additive: code_multiplicitive final { $$->expr = $1->expr; }; nonterm code_multiplicitive uses code_expr; code_multiplicitive: code_multiplicitive '*' code_unary final { $$->expr = LangExpr::cons( $2->loc, $1->expr, '*', $3->expr ); }; code_multiplicitive: code_multiplicitive '/' code_unary final { $$->expr = LangExpr::cons( $2->loc, $1->expr, '/', $3->expr ); }; code_multiplicitive: code_unary final { $$->expr = $1->expr; }; nonterm code_unary uses code_expr; code_unary: '!' code_factor final { $$->expr = LangExpr::cons( $1->loc, '!', $2->expr ); }; code_unary: '$' code_factor final { $$->expr = LangExpr::cons( $1->loc, '$', $2->expr ); }; code_unary: '^' code_factor final { $$->expr = LangExpr::cons( $1->loc, '^', $2->expr ); }; code_unary: '%' code_factor final { $$->expr = LangExpr::cons( $1->loc, '%', $2->expr ); }; code_unary: code_factor final { $$->expr = $1->expr; }; nonterm opt_capture uses var_def; opt_capture: TK_Word ':' final { $$->objField = ObjectField::cons( $1->loc, 0, $1->data ); }; opt_capture: final { $$->objField = 0; }; nonterm parse_cmd { bool stop; InputLoc loc; }; parse_cmd: KW_Parse final { $$->stop = false; $$->loc = $1->loc; }; parse_cmd: KW_ParseStop final { $$->stop = true; $$->loc = $1->loc; }; nonterm code_factor uses code_expr; code_factor: TK_Number final { $$->expr = LangExpr::cons( LangTerm::cons( InputLoc(), LangTerm::NumberType, $1->data ) ); }; code_factor: TK_Literal final { $$->expr = LangExpr::cons( LangTerm::cons( InputLoc(), LangTerm::StringType, $1->data ) ); }; code_factor: var_ref '(' opt_code_expr_list ')' final { $$->expr = LangExpr::cons( LangTerm::cons( InputLoc(), $1->varRef, $3->exprVect ) ); }; code_factor: var_ref final { $$->expr = LangExpr::cons( LangTerm::cons( InputLoc(), LangTerm::VarRefType, $1->varRef ) ); }; code_factor: KW_Match var_ref pattern final { $$->expr = match( $1->loc, $2->varRef, $3->list ); }; code_factor: KW_New code_factor final { $$->expr = LangExpr::cons( LangTerm::cons( InputLoc(), LangTerm::NewType, $2->expr ) ); }; code_factor: KW_Construct opt_capture type_ref opt_field_init constructor final { $$->expr = construct( $1->loc, $2->objField, $5->list, $3->typeRef, $4->fieldInitVect ); }; code_factor: parse_cmd opt_capture type_ref opt_field_init accumulate final { $$->expr = parseCmd( $1->loc, $1->stop, $2->objField, $3->typeRef, $4->fieldInitVect, $5->list ); }; code_factor: var_ref TK_LtLt accumulate final { $$->expr = send( $2->loc, $1->varRef, $3->list ); }; code_factor: KW_Send var_ref accumulate final { $$->expr = send( $1->loc, $2->varRef, $3->list ); }; code_factor: KW_TypeId '<' type_ref '>' final { $$->expr = LangExpr::cons( LangTerm::cons( $1->loc, LangTerm::TypeIdType, $3->typeRef ) ); }; code_factor: type_ref KW_In var_ref final { $$->expr = LangExpr::cons( LangTerm::cons( $2->loc, LangTerm::SearchType, $1->typeRef, $3->varRef ) ); }; code_factor: KW_Nil final { $$->expr = LangExpr::cons( LangTerm::cons( $1->loc, LangTerm::NilType ) ); }; code_factor: KW_True final { $$->expr = LangExpr::cons( LangTerm::cons( $1->loc, LangTerm::TrueType ) ); }; code_factor: KW_False final { $$->expr = LangExpr::cons( LangTerm::cons( $1->loc, LangTerm::FalseType ) ); }; code_factor: '(' code_expr ')' final { $$->expr = $2->expr; }; code_factor: KW_MakeTree '(' opt_code_expr_list ')' final { $$->expr = LangExpr::cons( LangTerm::cons( $1->loc, LangTerm::MakeTreeType, $3->exprVect ) ); }; code_factor: KW_MakeToken '(' opt_code_expr_list ')' final { $$->expr = LangExpr::cons( LangTerm::cons( $1->loc, LangTerm::MakeTokenType, $3->exprVect ) ); }; code_factor: KW_Deref code_expr final { $$->expr = LangExpr::cons( $1->loc, OP_Deref, $2->expr ); }; code_factor: string final { $$->expr = LangExpr::cons( LangTerm::cons( InputLoc(), $1->list ) ); }; nonterm opt_field_init uses field_init_list; opt_field_init: '(' opt_field_init_list ')' final { $$->fieldInitVect = $2->fieldInitVect; }; opt_field_init: final { $$->fieldInitVect = 0; }; nonterm opt_field_init_list uses field_init_list; opt_field_init_list: field_init_list final { $$->fieldInitVect = $1->fieldInitVect; }; opt_field_init_list: final { $$->fieldInitVect = 0; }; nonterm field_init_list { FieldInitVect *fieldInitVect; }; field_init_list: field_init_list field_init final { $$->fieldInitVect = $1->fieldInitVect; $$->fieldInitVect->append( $2->fieldInit ); }; field_init_list: field_init final { $$->fieldInitVect = new FieldInitVect; $$->fieldInitVect->append( $1->fieldInit ); }; nonterm field_init { FieldInit *fieldInit; }; field_init: code_expr final { $$->fieldInit = FieldInit::cons( InputLoc(), "_name", $1->expr ); }; # # Regular Expressions # nonterm opt_lex_join { LexJoin *join; }; opt_lex_join: lex_join opt_context final { $$->join = lexOptJoin( $1->join, $2->context ); }; opt_lex_join: final { $$->join = 0; }; nonterm lex_join { LexJoin *join; }; lex_join: lex_expr final { $$->join = LexJoin::cons( $1->expression ); }; nonterm opt_context { LexJoin *context; }; opt_context: '@' lex_join final { $$->context = $2->join; }; opt_context: final { $$->context = 0; }; nonterm lex_expr { LexExpression *expression; }; lex_expr: lex_expr '|' lex_term_short final { $$->expression = LexExpression::cons( $1->expression, $3->term, LexExpression::OrType ); }; lex_expr: lex_expr '&' lex_term_short final { $$->expression = LexExpression::cons( $1->expression, $3->term, LexExpression::IntersectType ); }; # This priority specification overrides the innermost parsing strategy which # results ordered choice interpretation of the grammar. lex_expr: lex_expr '-' lex_term_short final { $$->expression = LexExpression::cons( $1->expression, $3->term, LexExpression::SubtractType ); }; lex_expr: lex_expr TK_DashDash lex_term_short final { $$->expression = LexExpression::cons( $1->expression, $3->term, LexExpression::StrongSubtractType ); }; lex_expr: lex_term_short final { $$->expression = LexExpression::cons( $1->term ); }; nonterm lex_term_short { LexTerm *term; }; shortest lex_term_short; lex_term_short: lex_term final { $$->term = $1->term; }; nonterm lex_term { LexTerm *term; }; lex_term: lex_term lex_factor_label final { $$->term = LexTerm::cons( $1->term, $2->factorAug ); }; lex_term: lex_term '.' lex_factor_label final { $$->term = LexTerm::cons( $1->term, $3->factorAug ); }; lex_term: lex_term TK_ColonGt lex_factor_label final { $$->term = LexTerm::cons( $1->term, $3->factorAug, LexTerm::RightStartType ); }; lex_term: lex_term TK_ColonGtGt lex_factor_label final { $$->term = LexTerm::cons( $1->term, $3->factorAug, LexTerm::RightFinishType ); }; lex_term: lex_term TK_LtColon lex_factor_label final { $$->term = LexTerm::cons( $1->term, $3->factorAug, LexTerm::LeftType ); }; lex_term: lex_factor_label final { $$->term = LexTerm::cons( $1->factorAug ); }; nonterm lex_factor_label { LexFactorAug *factorAug; }; lex_factor_label: factor_ep final { $$->factorAug = $1->factorAug; }; lex_factor_label: TK_Word ':' lex_factor_label final { $$->factorAug = lexFactorLabel( $1->loc, $1->data, $3->factorAug ); }; nonterm factor_ep { LexFactorAug *factorAug; }; factor_ep: factor_aug final { $$->factorAug = $1->factorAug; }; nonterm factor_aug { LexFactorAug *factorAug; }; factor_aug: lex_factor_rep final { $$->factorAug = LexFactorAug::cons( $1->factorRep ); }; # The fourth level of precedence. These are the trailing unary operators that # allow for repetition. nonterm lex_factor_rep { LexFactorRep *factorRep; }; lex_factor_rep: lex_factor_rep '*' final { $$->factorRep = LexFactorRep::cons( $2->loc, $1->factorRep, 0, 0, LexFactorRep::StarType ); }; lex_factor_rep: lex_factor_rep TK_StarStar final { $$->factorRep = LexFactorRep::cons( $2->loc, $1->factorRep, 0, 0, LexFactorRep::StarStarType ); }; lex_factor_rep: lex_factor_rep '?' final { $$->factorRep = LexFactorRep::cons( $2->loc, $1->factorRep, 0, 0, LexFactorRep::OptionalType ); }; lex_factor_rep: lex_factor_rep '+' final { $$->factorRep = LexFactorRep::cons( $2->loc, $1->factorRep, 0, 0, LexFactorRep::PlusType ); }; lex_factor_rep: lex_factor_rep '{' lex_factor_rep_num '}' final { $$->factorRep = LexFactorRep::cons( $2->loc, $1->factorRep, $3->rep, 0, LexFactorRep::ExactType ); }; lex_factor_rep: lex_factor_rep '{' ',' lex_factor_rep_num '}' final { $$->factorRep = LexFactorRep::cons( $2->loc, $1->factorRep, 0, $4->rep, LexFactorRep::MaxType ); }; lex_factor_rep: lex_factor_rep '{' lex_factor_rep_num ',' '}' final { $$->factorRep = LexFactorRep::cons( $2->loc, $1->factorRep, $3->rep, 0, LexFactorRep::MinType ); }; lex_factor_rep: lex_factor_rep '{' lex_factor_rep_num ',' lex_factor_rep_num '}' final { $$->factorRep = LexFactorRep::cons( $2->loc, $1->factorRep, $3->rep, $5->rep, LexFactorRep::RangeType ); }; lex_factor_rep: lex_factor_neg final { $$->factorRep = LexFactorRep::cons( $1->factorNeg->loc, $1->factorNeg ); }; nonterm lex_factor_rep_num { int rep; }; lex_factor_rep_num: TK_UInt final { $$->rep = lexFactorRepNum( $1->loc, $1->data ); }; # # The fifth level up in precedence. Negation. # nonterm lex_factor_neg { LexFactorNeg *factorNeg; }; lex_factor_neg: '!' lex_factor_neg final { $$->factorNeg = LexFactorNeg::cons( $1->loc, $2->factorNeg, LexFactorNeg::NegateType ); }; lex_factor_neg: '^' lex_factor_neg final { $$->factorNeg = LexFactorNeg::cons( $1->loc, $2->factorNeg, LexFactorNeg::CharNegateType ); }; lex_factor_neg: lex_rl_factor final { $$->factorNeg = LexFactorNeg::cons( $1->factor->loc, $1->factor ); }; nonterm lex_rl_factor { LexFactor *factor; }; lex_rl_factor: TK_Literal final { /* Create a new factor node going to a concat literal. */ $$->factor = LexFactor::cons( Literal::cons( $1->loc, $1->data, Literal::LitString ) ); }; lex_rl_factor: lex_alphabet_num final { /* Create a new factor node going to a literal number. */ $$->factor = LexFactor::cons( Literal::cons( $1->loc, $1->data, Literal::Number ) ); }; lex_rl_factor: TK_Word final { $$->factor = lexRlFactorName( $1->data, $1->loc ); }; lex_rl_factor: TK_SqOpen lex_regular_expr_or_data TK_SqClose final { /* Create a new factor node going to an OR expression. */ $$->factor = LexFactor::cons( ReItem::cons( $1->loc, $2->reOrBlock, ReItem::OrBlock ) ); }; lex_rl_factor: TK_SqOpenNeg lex_regular_expr_or_data TK_SqClose final { /* Create a new factor node going to a negated OR expression. */ $$->factor = LexFactor::cons( ReItem::cons( $1->loc, $2->reOrBlock, ReItem::NegOrBlock ) ); }; lex_rl_factor: lex_range_lit TK_DotDot lex_range_lit final { /* Create a new factor node going to a range. */ $$->factor = LexFactor::cons( Range::cons( $1->literal, $3->literal ) ); }; lex_rl_factor: '(' lex_join ')' final { /* Create a new factor going to a parenthesized join. */ $$->factor = LexFactor::cons( $2->join ); }; nonterm lex_range_lit { Literal *literal; }; # Literals which can be the end points of ranges. lex_range_lit: TK_Literal final { /* Range literas must have only one char. We restrict this in the parse tree. */ $$->literal = Literal::cons( $1->loc, $1->data, Literal::LitString ); }; lex_range_lit: lex_alphabet_num final { /* Create a new literal number. */ $$->literal = Literal::cons( $1->loc, $1->data, Literal::Number ); }; nonterm lex_alphabet_num uses token_data; # Any form of a number that can be used as a basic machine. */ lex_alphabet_num: TK_UInt final { $$->loc = $1->loc; $$->data = $1->data; }; lex_alphabet_num: '-' TK_UInt final { $$->loc = $1->loc; $$->data = '+'; $$->data += $2->data; }; lex_alphabet_num: TK_Hex final { $$->loc = $1->loc; $$->data = $1->data; }; # # Regular Expressions. # # The data inside of a [] expression in a regular expression. Accepts any # number of characters or ranges. */ nonterm lex_regular_expr_or_data { ReOrBlock *reOrBlock; }; lex_regular_expr_or_data: lex_regular_expr_or_data lex_regular_expr_or_char final { $$->reOrBlock = lexRegularExprData( $1->reOrBlock, $2->reOrItem ); }; lex_regular_expr_or_data: final { $$->reOrBlock = ReOrBlock::cons(); }; # A single character inside of an or expression. Can either be a character or a # set of characters. nonterm lex_regular_expr_or_char { ReOrItem *reOrItem; }; lex_regular_expr_or_char: TK_ReChar final { $$->reOrItem = ReOrItem::cons( $1->loc, $1->data ); }; lex_regular_expr_or_char: TK_ReChar TK_Dash TK_ReChar final { $$->reOrItem = ReOrItem::cons( $2->loc, $1->data[0], $3->data[0] ); }; nonterm opt_commit { bool commit; }; opt_commit: final { $$->commit = false; }; opt_commit: KW_Commit final { $$->commit = true; }; # # Grammar Finished # write types; write data; }%% void ColmParser::init() { BaseParser::init(); %% write init; } int ColmParser::parseLangEl( int type, const Token *token ) { %% write exec; return errCount == 0 ? 0 : -1; } int ColmParser::token( InputLoc &loc, int tokId, char *tokstart, int toklen ) { Token token; if ( toklen > 0 ) token.data.setAs( tokstart, toklen ); token.loc = loc; int res = parseLangEl( tokId, &token ); if ( res < 0 ) { parse_error(tokId, token) << "parse error" << endl; exit(1); } return res; } ostream &ColmParser::parse_error( int tokId, Token &token ) { /* Maintain the error count. */ gblErrorCount += 1; cerr << token.loc.fileName << ":" << token.loc.line << ":" << token.loc.col << ": "; cerr << "at token "; if ( tokId < 128 ) cerr << "\"" << ColmParser_lelNames[tokId] << "\""; else cerr << ColmParser_lelNames[tokId]; if ( token.data != 0 ) cerr << " with data \"" << token.data << "\""; cerr << ": "; return cerr; }