diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/ast/ast.cpp | 31 | ||||
-rw-r--r-- | src/ast/ast.hpp | 3 | ||||
-rw-r--r-- | src/ast/expr.cpp | 52 | ||||
-rw-r--r-- | src/ast/expr.hpp | 22 | ||||
-rw-r--r-- | src/ast/pattern.hpp | 2 | ||||
-rw-r--r-- | src/dump_as_rust.cpp | 24 | ||||
-rw-r--r-- | src/parse/expr.cpp | 95 | ||||
-rw-r--r-- | src/parse/lex.hpp | 29 | ||||
-rw-r--r-- | src/parse/parseerror.cpp | 5 | ||||
-rw-r--r-- | src/parse/parseerror.hpp | 1 | ||||
-rw-r--r-- | src/parse/root.cpp | 37 |
11 files changed, 244 insertions, 57 deletions
diff --git a/src/ast/ast.cpp b/src/ast/ast.cpp index e6187001..8a903cca 100644 --- a/src/ast/ast.cpp +++ b/src/ast/ast.cpp @@ -48,8 +48,10 @@ SERIALISE_TYPE(MetaItem::, "AST_MetaItem", { case Pattern::MAYBE_BIND:
os << "Pattern(TagMaybeBind, '" << pat.m_binding << "')";
break;
+ case Pattern::REF:
+ os << "Pattern(TagReference, '" << pat.m_binding << "' @ " << pat.m_sub_patterns[0] << ")";
+ break;
case Pattern::VALUE:
- //os << "Pattern(TagValue, " << *pat.m_node << ")";
os << "Pattern(TagValue, '" << pat.m_binding << "' @ TODO:ExprNode)";
break;
case Pattern::TUPLE:
@@ -64,18 +66,28 @@ SERIALISE_TYPE(MetaItem::, "AST_MetaItem", { void operator%(Serialiser& s, Pattern::BindType c) {
switch(c)
{
- case Pattern::ANY: s << "ANY"; return;
- case Pattern::MAYBE_BIND: s << "MAYBE_BIND"; return;
- case Pattern::VALUE: s << "VALUE"; return;
- case Pattern::TUPLE: s << "TUPLE"; return;
- case Pattern::TUPLE_STRUCT: s << "TUPLE_STRUCT"; return;
+ #define _(v) case Pattern::v: s << #v; return;
+ _(ANY)
+ _(MAYBE_BIND)
+ _(REF)
+ _(VALUE)
+ _(TUPLE)
+ _(TUPLE_STRUCT)
+ #undef _
}
}
void operator%(::Deserialiser& s, Pattern::BindType& c) {
::std::string n;
s.item(n);
- if(n == "ANY") c = Pattern::ANY;
- else if(n == "MAYBE_BIND") c = Pattern::MAYBE_BIND;
+ if(1) ;
+ #define _(v) else if(n == #v) c = Pattern::v;
+ _(ANY)
+ _(MAYBE_BIND)
+ _(REF)
+ _(VALUE)
+ _(TUPLE)
+ _(TUPLE_STRUCT)
+ #undef _
else
throw ::std::runtime_error("");
}
@@ -89,6 +101,8 @@ SERIALISE_TYPE_S(Pattern, { Impl Impl::make_concrete(const ::std::vector<TypeRef>& types) const
{
DEBUG("types={" << types << "}");
+ throw ParseError::Todo("Impl::make_concrete");
+/*
INDENT();
assert(m_params.n_params());
@@ -120,6 +134,7 @@ Impl Impl::make_concrete(const ::std::vector<TypeRef>& types) const UNINDENT();
return ret;
+*/
}
::rust::option<Impl&> Impl::matches(const TypeRef& trait, const TypeRef& type)
diff --git a/src/ast/ast.hpp b/src/ast/ast.hpp index 775ed943..c1c9c283 100644 --- a/src/ast/ast.hpp +++ b/src/ast/ast.hpp @@ -268,6 +268,7 @@ public: private:
Class m_fcn_class;
+ ::std::string m_lifetime;
TypeParams m_params;
Expr m_code;
TypeRef m_rettype;
@@ -285,6 +286,8 @@ public: {
}
+ void set_self_lifetime(::std::string s) { m_lifetime = s; }
+
const Class fcn_class() const { return m_fcn_class; }
TypeParams& params() { return m_params; }
diff --git a/src/ast/expr.cpp b/src/ast/expr.cpp index 3e20655d..9ddd75a9 100644 --- a/src/ast/expr.cpp +++ b/src/ast/expr.cpp @@ -60,6 +60,7 @@ SERIALISE_TYPE(Expr::, "Expr", { else _(ExprNode_CallObject) else _(ExprNode_Match) else _(ExprNode_If) + else _(ExprNode_IfLet) else _(ExprNode_Integer) else _(ExprNode_StructLiteral) else _(ExprNode_Tuple) @@ -178,6 +179,14 @@ NODE(ExprNode_If, { },{ os << "if " << *m_cond << " { " << *m_true << " } else { " << *m_false << " }"; }) +NODE(ExprNode_IfLet, { + s.item(m_pattern); + s.item(m_value); + s.item(m_true); + s.item(m_false); +},{ + os << "if let " << m_pattern << " = (" << *m_value << ") { " << *m_true << " } else { " << *m_false << " }"; +}) NODE(ExprNode_Integer, { s % m_datatype; @@ -247,6 +256,10 @@ void operator%(::Serialiser& s, const ExprNode_BinOp::Type t) { #define _(v) case ExprNode_BinOp::v: s << #v; return _(CMPEQU); _(CMPNEQU); + _(CMPLT); + _(CMPLTE); + _(CMPGT); + _(CMPGTE); _(BOOLAND); _(BOOLOR); _(BITAND); @@ -257,18 +270,37 @@ void operator%(::Serialiser& s, const ExprNode_BinOp::Type t) { _(MULTIPLY); _(DIVIDE); _(MODULO); + _(ADD); + _(SUB); #undef _ } } void operator%(::Deserialiser& s, ExprNode_BinOp::Type& t) { ::std::string n; s.item(n); - #define _(v) if(n == #v) t = ExprNode_BinOp::v - _(CMPEQU); - else _(CMPNEQU); + if(0) ; + #define _(v) else if(n == #v) t = ExprNode_BinOp::v + _(CMPEQU); + _(CMPNEQU); + _(CMPLT); + _(CMPLTE); + _(CMPGT); + _(CMPGTE); + _(BOOLAND); + _(BOOLOR); + _(BITAND); + _(BITOR); + _(BITXOR); + _(SHL); + _(SHR); + _(MULTIPLY); + _(DIVIDE); + _(MODULO); + _(ADD); + _(SUB); + #undef _ else throw ::std::runtime_error(""); - #undef _ } NODE(ExprNode_BinOp, { s % m_type; @@ -280,6 +312,10 @@ NODE(ExprNode_BinOp, { { case CMPEQU: os << "=="; break; case CMPNEQU: os << "!="; break; + case CMPLT: os << "<"; break; + case CMPLTE: os << "<="; break; + case CMPGT: os << ">"; break; + case CMPGTE: os << ">="; break; case BOOLAND: os << "&&"; break; case BOOLOR: os << "||"; break; case BITAND: os << "&"; break; @@ -402,6 +438,14 @@ NV(ExprNode_If, visit(node.m_false); UNINDENT(); }) +NV(ExprNode_IfLet, +{ + INDENT(); + visit(node.m_value); + visit(node.m_true); + visit(node.m_false); + UNINDENT(); +}) NV(ExprNode_Integer, {}) NV(ExprNode_Float, {}) diff --git a/src/ast/expr.hpp b/src/ast/expr.hpp index 28526377..55da44d6 100644 --- a/src/ast/expr.hpp +++ b/src/ast/expr.hpp @@ -202,6 +202,24 @@ struct ExprNode_If: } NODE_METHODS(); }; +struct ExprNode_IfLet: + public ExprNode +{ + AST::Pattern m_pattern; + unique_ptr<ExprNode> m_value; + unique_ptr<ExprNode> m_true; + unique_ptr<ExprNode> m_false; + + ExprNode_IfLet() {} + ExprNode_IfLet(AST::Pattern pattern, unique_ptr<ExprNode>&& cond, unique_ptr<ExprNode>&& true_code, unique_ptr<ExprNode>&& false_code): + m_pattern( ::std::move(pattern) ), + m_value( ::std::move(cond) ), + m_true( ::std::move(true_code) ), + m_false( ::std::move(false_code) ) + { + } + NODE_METHODS(); +}; // Literal integer struct ExprNode_Integer: public ExprNode @@ -363,6 +381,8 @@ struct ExprNode_BinOp: MULTIPLY, DIVIDE, MODULO, + ADD, + SUB, }; Type m_type; @@ -425,6 +445,7 @@ public: NT(ExprNode_CallObject); NT(ExprNode_Match); NT(ExprNode_If); + NT(ExprNode_IfLet); NT(ExprNode_Integer); NT(ExprNode_Float); @@ -461,6 +482,7 @@ public: NT(ExprNode_CallObject); NT(ExprNode_Match); NT(ExprNode_If); + NT(ExprNode_IfLet); NT(ExprNode_Integer); NT(ExprNode_Float); diff --git a/src/ast/pattern.hpp b/src/ast/pattern.hpp index 78b224d0..5b03a8a2 100644 --- a/src/ast/pattern.hpp +++ b/src/ast/pattern.hpp @@ -32,7 +32,7 @@ private: unique_ptr<ExprNode> m_node; ::std::vector<Pattern> m_sub_patterns; public: - Pattern(Pattern&& o): + Pattern(Pattern&& o) noexcept: m_class(o.m_class), m_binding( move(o.m_binding) ), m_path( move(o.m_path) ), diff --git a/src/dump_as_rust.cpp b/src/dump_as_rust.cpp index e5d225bd..c9a64371 100644 --- a/src/dump_as_rust.cpp +++ b/src/dump_as_rust.cpp @@ -155,6 +155,21 @@ public: m_expr_root = false; m_os << "if "; AST::NodeVisitor::visit(n.m_cond); + + visit_if_common(expr_root, n.m_true, n.m_false); + } + virtual void visit(AST::ExprNode_IfLet& n) override { + bool expr_root = m_expr_root; + m_expr_root = false; + m_os << "if let "; + print_pattern(n.m_pattern); + m_os << " = "; + AST::NodeVisitor::visit(n.m_value); + + visit_if_common(expr_root, n.m_true, n.m_false); + } + void visit_if_common(bool expr_root, const ::std::unique_ptr<AST::ExprNode>& tv, const ::std::unique_ptr<AST::ExprNode>& fv) + { if( expr_root ) { m_os << "\n"; @@ -164,15 +179,16 @@ public: { m_os << " "; } - AST::NodeVisitor::visit(n.m_true); - if(n.m_false.get()) + + AST::NodeVisitor::visit(tv); + if(fv.get()) { if( expr_root ) { m_os << "\n"; m_os << indent() << "else"; // handle chained if statements nicely - if( IS(*n.m_false, AST::ExprNode_If) ) { + if( IS(*fv, AST::ExprNode_If) || IS(*fv, AST::ExprNode_IfLet) ) { m_expr_root = true; m_os << " "; } @@ -183,7 +199,7 @@ public: { m_os << " else "; } - AST::NodeVisitor::visit(n.m_false); + AST::NodeVisitor::visit(fv); } } virtual void visit(AST::ExprNode_Integer& n) override { diff --git a/src/parse/expr.cpp b/src/parse/expr.cpp index 2ae94794..7fb41b0f 100644 --- a/src/parse/expr.cpp +++ b/src/parse/expr.cpp @@ -16,6 +16,7 @@ ExprNodeP Parse_ExprBlockNode(TokenStream& lex); ExprNodeP Parse_Stmt(TokenStream& lex, bool& opt_semicolon);
ExprNodeP Parse_Expr0(TokenStream& lex);
ExprNodeP Parse_ExprBlocks(TokenStream& lex);
+ExprNodeP Parse_IfStmt(TokenStream& lex);
ExprNodeP Parse_Expr1(TokenStream& lex);
AST::Expr Parse_Expr(TokenStream& lex, bool const_only)
@@ -175,7 +176,9 @@ AST::Pattern Parse_PatternReal_Path(TokenStream& lex, AST::Path path) Token tok;
::std::vector<AST::Pattern> child_pats;
do {
- child_pats.push_back( Parse_Pattern(lex) );
+ AST::Pattern pat = Parse_Pattern(lex);
+ DEBUG("pat = " << pat);
+ child_pats.push_back( ::std::move(pat) );
} while( GET_TOK(tok, lex) == TOK_COMMA );
CHECK_TOK(tok, TOK_PAREN_CLOSE);
return child_pats;
@@ -251,6 +254,9 @@ ExprNodeP Parse_Stmt(TokenStream& lex, bool& opt_semicolon) throw ParseError::Todo("for");
case TOK_RWORD_WHILE:
throw ParseError::Todo("while");
+ case TOK_RWORD_IF:
+ opt_semicolon = true;
+ return Parse_IfStmt(lex);
default:
lex.putback(tok);
return Parse_Expr0(lex);
@@ -299,11 +305,17 @@ ExprNodeP Parse_Expr0(TokenStream& lex) ExprNodeP Parse_IfStmt(TokenStream& lex)
{
TRACE_FUNCTION;
+ SET_PARSE_FLAG(lex, disallow_struct_literal);
Token tok;
ExprNodeP cond;
+ AST::Pattern pat;
+ bool if_let = false;
if( GET_TOK(tok, lex) == TOK_RWORD_LET ) {
- throw ParseError::Todo("if let");
+ if_let = true;
+ pat = Parse_Pattern(lex);
+ GET_CHECK_TOK(tok, lex, TOK_EQUAL);
+ cond = Parse_Expr0(lex);
}
else {
lex.putback(tok);
@@ -332,7 +344,10 @@ ExprNodeP Parse_IfStmt(TokenStream& lex) lex.putback(tok);
}
- return NEWNODE( AST::ExprNode_If, ::std::move(cond), ::std::move(code), ::std::move(altcode) );
+ if( if_let )
+ return NEWNODE( AST::ExprNode_IfLet, ::std::move(pat), ::std::move(cond), ::std::move(code), ::std::move(altcode) );
+ else
+ return NEWNODE( AST::ExprNode_If, ::std::move(cond), ::std::move(code), ::std::move(altcode) );
}
ExprNodeP Parse_Expr_Match(TokenStream& lex)
@@ -479,9 +494,11 @@ LEFTASSOC(Parse_Expr8, Parse_Expr9, // 9: Add / Subtract
LEFTASSOC(Parse_Expr9, Parse_Expr10,
case TOK_PLUS:
- throw ParseError::Todo("expr - add");
+ rv = NEWNODE( AST::ExprNode_BinOp, AST::ExprNode_BinOp::ADD, ::std::move(rv), next(lex));
+ break;
case TOK_DASH:
- throw ParseError::Todo("expr - sub");
+ rv = NEWNODE( AST::ExprNode_BinOp, AST::ExprNode_BinOp::SUB, ::std::move(rv), next(lex));
+ break;
)
// 10: Cast
LEFTASSOC(Parse_Expr10, Parse_Expr11,
@@ -563,6 +580,37 @@ ExprNodeP Parse_ExprFC(TokenStream& lex) }
}
+ExprNodeP Parse_ExprVal_StructLiteral(TokenStream& lex, AST::Path path)
+{
+ TRACE_FUNCTION;
+ Token tok;
+
+ // Braced structure literal
+ // - A series of 0 or more pairs of <ident>: <expr>,
+ // - '..' <expr>
+ ::std::vector< ::std::pair< ::std::string, ::std::unique_ptr<AST::ExprNode>> > items;
+ while( GET_TOK(tok, lex) == TOK_IDENT )
+ {
+ ::std::string name = tok.str();
+ GET_CHECK_TOK(tok, lex, TOK_COLON);
+ ExprNodeP val = Parse_Expr0(lex);
+ items.push_back( ::std::make_pair(::std::move(name), ::std::move(val)) );
+ if( GET_TOK(tok,lex) == TOK_BRACE_CLOSE )
+ break;
+ CHECK_TOK(tok, TOK_COMMA);
+ }
+ ExprNodeP base_val;
+ if( tok.type() == TOK_DOUBLE_DOT )
+ {
+ // default
+ base_val = Parse_Expr0(lex);
+ GET_TOK(tok, lex);
+ }
+ CHECK_TOK(tok, TOK_BRACE_CLOSE);
+
+ return NEWNODE( AST::ExprNode_StructLiteral, path, ::std::move(base_val), ::std::move(items) );
+}
+
ExprNodeP Parse_ExprVal(TokenStream& lex)
{
TRACE_FUNCTION;
@@ -580,37 +628,13 @@ ExprNodeP Parse_ExprVal(TokenStream& lex) path = Parse_Path(lex, true, PATH_GENERIC_EXPR);
switch( GET_TOK(tok, lex) )
{
- case TOK_BRACE_OPEN: {
- // Braced structure literal
- // - A series of 0 or more pairs of <ident>: <expr>,
- // - '..' <expr>
- ::std::vector< ::std::pair< ::std::string, ::std::unique_ptr<AST::ExprNode>> > items;
- while( GET_TOK(tok, lex) == TOK_IDENT )
- {
- ::std::string name = tok.str();
- GET_CHECK_TOK(tok, lex, TOK_COLON);
- ExprNodeP val = Parse_Expr0(lex);
- items.push_back( ::std::make_pair(::std::move(name), ::std::move(val)) );
- if( GET_TOK(tok,lex) == TOK_BRACE_CLOSE )
- break;
- CHECK_TOK(tok, TOK_COMMA);
- }
- ExprNodeP base_val;
- if( tok.type() == TOK_DOUBLE_DOT )
- {
- // default
- base_val = Parse_Expr0(lex);
- GET_TOK(tok, lex);
- }
- CHECK_TOK(tok, TOK_BRACE_CLOSE);
- return NEWNODE( AST::ExprNode_StructLiteral, path, ::std::move(base_val), ::std::move(items) );
- }
- case TOK_PAREN_OPEN: {
- lex.putback(tok);
+ case TOK_PAREN_OPEN:
// Function call
- ::std::vector<ExprNodeP> args = Parse_ParenList(lex);
- return NEWNODE( AST::ExprNode_CallPath, ::std::move(path), ::std::move(args) );
- }
+ lex.putback(tok);
+ return NEWNODE( AST::ExprNode_CallPath, ::std::move(path), Parse_ParenList(lex) );
+ case TOK_BRACE_OPEN:
+ if( !CHECK_PARSE_FLAG(lex, disallow_struct_literal) )
+ return Parse_ExprVal_StructLiteral(lex, ::std::move(path));
default:
// Value
lex.putback(tok);
@@ -634,6 +658,7 @@ ExprNodeP Parse_ExprVal(TokenStream& lex) }
else
{
+ CLEAR_PARSE_FLAG(lex, disallow_struct_literal);
lex.putback(tok);
ExprNodeP rv = Parse_Expr0(lex);
diff --git a/src/parse/lex.hpp b/src/parse/lex.hpp index d28b0afd..41bac795 100644 --- a/src/parse/lex.hpp +++ b/src/parse/lex.hpp @@ -56,20 +56,49 @@ struct Position }; extern ::std::ostream& operator<<(::std::ostream& os, const Position& p); +/// State the parser needs to pass down via a second channel. +struct ParseState +{ + bool disallow_struct_literal = false; +}; + class TokenStream { bool m_cache_valid; Token m_cache; + ParseState m_parse_state; public: TokenStream(); virtual ~TokenStream(); Token getToken(); void putback(Token tok); virtual Position getPosition() const = 0; + + ParseState& parse_state() { return m_parse_state; } + protected: virtual Token realGetToken() = 0; }; +class SavedParseState +{ + TokenStream& m_lex; + ParseState m_state; +public: + SavedParseState(TokenStream& lex, ParseState state): + m_lex(lex), + m_state(state) + {} + ~SavedParseState() + { + m_lex.parse_state() = m_state; + } +}; + +#define SET_PARSE_FLAG(lex, flag) SavedParseState(lex, lex.parse_state()); lex.parse_state().flag = true +#define CLEAR_PARSE_FLAG(lex, flag) SavedParseState(lex, lex.parse_state()); lex.parse_state().flag = false +#define CHECK_PARSE_FLAG(lex, flag) (lex.parse_state().flag == true) + class Lexer { ::std::ifstream m_istream; diff --git a/src/parse/parseerror.cpp b/src/parse/parseerror.cpp index ed7a845c..b0674c07 100644 --- a/src/parse/parseerror.cpp +++ b/src/parse/parseerror.cpp @@ -24,6 +24,11 @@ ParseError::Todo::Todo(::std::string message): {
::std::cout << "Todo(" << message << ")" << ::std::endl;
}
+ParseError::Todo::Todo(const TokenStream& lex, ::std::string message):
+ m_message(message)
+{
+ ::std::cout << lex.getPosition() << ": Todo(" << message << ")" << ::std::endl;
+}
ParseError::Todo::~Todo() throw()
{
}
diff --git a/src/parse/parseerror.hpp b/src/parse/parseerror.hpp index 33c02a92..5868f629 100644 --- a/src/parse/parseerror.hpp +++ b/src/parse/parseerror.hpp @@ -37,6 +37,7 @@ class Todo: ::std::string m_message;
public:
Todo(::std::string message);
+ Todo(const TokenStream& lex, ::std::string message);
virtual ~Todo() throw ();
};
diff --git a/src/parse/root.cpp b/src/parse/root.cpp index f5f48132..e3d0ac0a 100644 --- a/src/parse/root.cpp +++ b/src/parse/root.cpp @@ -12,12 +12,23 @@ extern AST::Pattern Parse_Pattern(TokenStream& lex); ::std::vector<TypeRef> Parse_Path_GenericList(TokenStream& lex)
{
TRACE_FUNCTION;
+ Token tok;
::std::vector<TypeRef> types;
- Token tok;
+ ::std::vector< ::std::string> lifetimes;
do {
- types.push_back( Parse_Type(lex) );
+ switch(GET_TOK(tok, lex))
+ {
+ case TOK_LIFETIME:
+ lifetimes.push_back( tok.str() );
+ break;
+ default:
+ lex.putback(tok);
+ types.push_back( Parse_Type(lex) );
+ break;
+ }
} while( GET_TOK(tok, lex) == TOK_COMMA );
+
// HACK: Split >> into >
if(tok.type() == TOK_DOUBLE_GT) {
lex.putback(Token(TOK_GT));
@@ -25,6 +36,8 @@ extern AST::Pattern Parse_Pattern(TokenStream& lex); else {
CHECK_TOK(tok, TOK_GT);
}
+
+
return types;
}
@@ -293,14 +306,18 @@ AST::Function Parse_FunctionDef(TokenStream& lex, bool allow_no_code=false) }
AST::Function::Class fcn_class = AST::Function::CLASS_UNBOUND;
+ AST::Function::Arglist args;
+
GET_CHECK_TOK(tok, lex, TOK_PAREN_OPEN);
GET_TOK(tok, lex);
if( tok.type() == TOK_AMP )
{
// By-reference method
+ ::std::string lifetime;
if( GET_TOK(tok, lex) == TOK_LIFETIME )
{
- throw ParseError::Todo("Lifetimes on self in methods");
+ lifetime = tok.str();
+ GET_TOK(tok, lex);
}
if( tok.type() == TOK_RWORD_MUT )
{
@@ -312,6 +329,8 @@ AST::Function Parse_FunctionDef(TokenStream& lex, bool allow_no_code=false) CHECK_TOK(tok, TOK_RWORD_SELF);
fcn_class = AST::Function::CLASS_REFMETHOD;
}
+ DEBUG("TODO: UFCS / self lifetimes");
+ //args.push_back( ::std::make_pair( AST::Pattern(), TypeRef(TypeRef::TagReference(), lifetime, (fcn_class == AST::Function::CLASS_MUTMETHOD), ) ) );
GET_TOK(tok, lex);
}
else if( tok.type() == TOK_RWORD_SELF )
@@ -325,10 +344,17 @@ AST::Function Parse_FunctionDef(TokenStream& lex, bool allow_no_code=false) // Unbound method
}
- AST::Function::Arglist args;
if( tok.type() != TOK_PAREN_CLOSE )
{
- lex.putback(tok);
+ // Comma after self
+ if( fcn_class != AST::Function::CLASS_UNBOUND )
+ {
+ CHECK_TOK(tok, TOK_COMMA);
+ }
+ else {
+ lex.putback(tok);
+ }
+
// Argument list
do {
AST::Pattern pat = Parse_Pattern(lex);
@@ -992,6 +1018,7 @@ void Parse_ModRoot(Preproc& lex, AST::Crate& crate, AST::Module& mod, LList<AST: {
throw ParseError::Unexpected(lex, tok);
}
+ crate.load_extern_crate(path);
mod.add_ext_crate(path, name);
GET_CHECK_TOK(tok, lex, TOK_SEMICOLON);
break; }
|