@weixin
2015-04-16T16:34:40.000000Z
字数 4278
阅读 1188
compile
<INITIAL>"function" return FUNCTION;
<INITIAL>"if" return IF;
<INITIAL>"else" return ELSE;
...
<INITIAL>"-" return SUB;
<INITIAL>"*" return MUL;
<INITIAL>"/" return DIV;
<INITIAL>"%" return MOD;
<INITIAL>[A-Za-z_][A-Za-z_0-9]* {
yylval.identifier = crb_create_identifier(yytext);
return IDENTIFIER;
}
identifier
and add the memory to the interpreter->interpreter-storage
<INITIAL>([1-9][0-9]*)|"0" {
Expression *expression = crb_alloc_expression(INT_EXPRESSION);
sscanf(yytext, "%d", &expression->u.int_value);
yylval.expression = expression;
return INT_LITERAL;
}
expression
and add the memory to the interpreter->interpreter-storage
<INITIAL>\" {
crb_open_string_literal();
BEGIN STRING_LITERAL_STATE;
}
"
, then begin STRING_LITERAL_STATE
<STRING_LITERAL_STATE>\" {
Expression *expression = crb_alloc_expression(STRING_EXPRESSION);
expression->u.string_value = crb_close_string_literal();
yylval.expression = expression;
BEGIN INITIAL;
return STRING_LITERAL;
}
<STRING_LITERAL_STATE>\n {
crb_add_string_literal('\n');
increment_line_number();
}
<STRING_LITERAL_STATE>\\\" crb_add_string_literal('"');
<STRING_LITERAL_STATE>\\n crb_add_string_literal('\n');
<STRING_LITERAL_STATE>\\t crb_add_string_literal('\t');
<STRING_LITERAL_STATE>\\\\ crb_add_string_literal('\\');
<STRING_LITERAL_STATE>. crb_add_string_literal(yytext[0]);
when it is in STRING_LITERAL_STATE
, if see another "
, then the string is closed, the allocate a string expression in interpreter. then BEGIN INITIAL
, return to the initial status.
<INITIAL>. {
char buf[LINE_BUF_SIZE];
if (isprint(yytext[0])) {
buf[0] = yytext[0];
buf[1] = '\0';
} else {
sprintf(buf, "0x%02x", (unsigned char)yytext[0]);
}
crb_compile_error(CHARACTER_INVALID_ERR,
STRING_MESSAGE_ARGUMENT, "bad_char", buf,
MESSAGE_ARGUMENT_END);
}
.
stands for any character other than the pre-defined <INITIAL> isprint
is a c standard lib function, check if the char printable or not, then report compiler error.
function_definition
: FUNCTION IDENTIFIER LP parameter_list RP block
{
crb_function_define($2, $4, $6);
}
| FUNCTION IDENTIFIER LP RP block
{
crb_function_define($2, NULL, $5);
}
;
in crowbar, the function syntax like this :
function func_name(param1, param2..){}
or function func_name(){}
parameter_list
: IDENTIFIER
{
$$ = crb_create_parameter($1);
}
| parameter_list COMMA IDENTIFIER
{
$$ = crb_chain_parameter($1, $3);
}
;
argument_list
: expression
{
$$ = crb_create_argument_list($1);
}
| argument_list COMMA expression
{
$$ = crb_chain_argument_list($1, $3);
}
;
what's the differences between parmeter and argument? here is a link : parameter vs argument
function A(p1,p2)
, p1
, p2
are parameters, which are part of method signature.
b = A(arg1,arg2)
, arg1
and arg2
are arguments, which passed in when you call the method.
think parameter is a parking lot, or placeholder, argument is a car.
expression
: logical_or_expression
| IDENTIFIER ASSIGN expression
{
$$ = crb_create_assign_expression($1, $3);
}
;
logical_or_expression
: logical_and_expression
| logical_or_expression LOGICAL_OR logical_and_expression
{
$$ = crb_create_binary_expression(LOGICAL_OR_EXPRESSION, $1, $3);
}
;
crb_create_binary_expression
would create a binary tree. the workflow is like this :after checking expresison type, if the type is INT_EXPRESSION
or DOUBLE_EXPRESSION
, then it will crb_eval_binary_expression
, this is called variable folding.
statement
: expression SEMICOLON
{
$$ = crb_create_expression_statement($1);
}
| global_statement
| if_statement
| while_statement
| for_statement
| return_statement
| break_statement
| continue_statement
;
global_statement
: GLOBAL_T identifier_list SEMICOLON
{
$$ = crb_create_global_statement($2);
}
;
....
if_statement
: IF LP expression RP block
{
$$ = crb_create_if_statement($3, $5, NULL, NULL);
}
| IF LP expression RP block ELSE block
{
$$ = crb_create_if_statement($3, $5, NULL, $7);
}
| IF LP expression RP block elsif_list
{
$$ = crb_create_if_statement($3, $5, $6, NULL);
}
| IF LP expression RP block elsif_list ELSE block
{
$$ = crb_create_if_statement($3, $5, $6, $8);
}
;