/* -*- indented-text -*- */ /* Copyright 1999 Zanshin Inc. * * The contents of this file are subject to the Zanshin Public License Version * 1.0 (the "License"); you may not use this file except in compliance with the * License. You should have received a copy of the License with Latte; see * the file COPYING. You may also obtain a copy of the License at * . * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Latte. * * The Initial Developer of the Original Code is Zanshin, Inc. */ %pure_parser %{ #include using namespace std; struct Tangible { Tangible(const Latte_Wstate &w, const Latte_FileLoc &l) : ws(w), loc(l) {} Latte_Wstate ws; Latte_FileLoc loc; }; %} %union { Latte_Obj *expr; Latte_Group *group; shstring *str; Latte_Assignment *assignment; Latte_Quote *quote; struct Tangible *tangible; } %{ struct latteparse_control { Latte_Reader *lexer; Latte_Visitor *visitor; Latte_Wstate ws; Latte_FileLoc loc; }; extern int lattelex(YYSTYPE *, void *); extern void latteerror(const char *); #define YYPARSE_PARAM param #define YYLEX_PARAM param #define PARAM ((latteparse_control *) param) %} %type expr %type exprs %start top %token PARAM_ASSIGN %token PARAM_NAME %token REST_PARAM %token STR %token VAR_REF %token QUASIQUOTE %token QUOTE %token UNQUOTE %token UNQUOTE_SPLICING %% top: top expr { Refcounter obj($2); Refcounter val(obj->eval(PARAM->lexer->global_activation())); val->visit(*(PARAM->visitor)); } | ; expr: VAR_REF { $$ = new Latte_VarRef(PARAM->ws, PARAM->loc, *$1); } | PARAM_NAME { $$ = new Latte_Param(PARAM->ws, PARAM->loc, *$1, Latte_Param::type_named); } | PARAM_ASSIGN { $$ = new Latte_Assignment(PARAM->ws, PARAM->loc, *$1); } expr { $2->set_nested_obj(Refcounter($3)); $$ = $2; } | REST_PARAM { $$ = new Latte_Param(PARAM->ws, PARAM->loc, *$1, Latte_Param::type_rest); } | QUOTE { $$ = new Latte_Quote(PARAM->ws, PARAM->loc, Latte_Quote::type_quote); } expr { $2->set_obj(Refcounter($3)); $$ = $2; } | QUASIQUOTE { $$ = new Latte_Quote(PARAM->ws, PARAM->loc, Latte_Quote::type_quasiquote); } expr { $2->set_obj(Refcounter($3)); $$ = $2; } | UNQUOTE { $$ = new Latte_Quote(PARAM->ws, PARAM->loc, Latte_Quote::type_unquote); } expr { $2->set_obj(Refcounter($3)); $$ = $2; } | UNQUOTE_SPLICING { $$ = new Latte_Quote(PARAM->ws, PARAM->loc, Latte_Quote::type_unquote_splicing); } expr { $2->set_obj(Refcounter($3)); $$ = $2; } | '{' { $$ = new Tangible(PARAM->ws, PARAM->loc); } exprs '}' { $3->set_ws($2->ws); $3->set_fileloc($2->loc); delete $2; $$ = $3; } | STR { $$ = new Latte_Str(PARAM->ws, PARAM->loc, *$1); } | error { throw Latte_Reader::SyntaxError(PARAM->loc); }; exprs: exprs expr { $1->push_back(Refcounter($2)); $$ = $1; } | { $$ = new Latte_Group(PARAM->ws, PARAM->loc); } ; %% int lattelex(YYSTYPE *lvalp, void *param) { int result = PARAM->lexer->yylex(); PARAM->ws = PARAM->lexer->ws().transfer(); PARAM->loc = Latte_FileLoc(PARAM->lexer->filename(), PARAM->lexer->lineno()); switch (result) { case PARAM_ASSIGN: lvalp->str = new shstring(PARAM->lexer->YYText() + 1, PARAM->lexer->YYLeng() - 2); break; case PARAM_NAME: lvalp->str = new shstring(PARAM->lexer->YYText() + 2, PARAM->lexer->YYLeng() - 2); break; case REST_PARAM: lvalp->str = new shstring(PARAM->lexer->YYText() + 2, PARAM->lexer->YYLeng() - 2); break; case STR: { string result(PARAM->lexer->YYText(), PARAM->lexer->YYLeng()); size_t p = 0; while (p < result.size()) { if (result[p] == '\\') result.erase(p, 1); ++p; } lvalp->str = new shstring(result); break; } case VAR_REF: lvalp->str = new shstring(PARAM->lexer->YYText() + 1, PARAM->lexer->YYLeng() - 1); break; } return result; } void Latte_Reader::process(Latte_Visitor &visitor) { latteparse_control control; control.lexer = this; control.visitor = &visitor; try { if (latteparse((void *) &control)) throw Incomplete(Latte_FileLoc(m_filename, lineno())); } catch(Latte_Error err) { err.set_fileloc(Latte_FileLoc(m_filename, lineno())); throw; }; } void latteerror(const char *s) { }