Итак, этот вопрос не обязательно является моей проблемой, скорее это недостаток понимания.
У меня есть этот код ANTLR (который включает в себя синтаксический анализатор и лексер):
grammar Compiler;
prog
: Class Program '{' field_decls method_decls '}'
;
field_decls returns [String s1]
: field_decls field_decl ';'
{
$s1 = $field_decl.s2;
}
| field_decls inited_field_decl ';'
|
;
field_decl returns [String s2]
: field_decl ',' Ident
| field_decl ',' Ident '[' num ']'
| Type Ident
{
System.out.println($Ident.text);
$s2 = $Ident.text;
}
| Type Ident '[' num ']'
{
System.out.println($Ident.text+"["+"]");
$s2 = $Ident.text;
}
;
inited_field_decl
: Type Ident '=' literal
;
method_decls
: method_decls method_decl
|
;
method_decl
: Void Ident '(' params ')' block
| Type Ident '(' params ')' block
;
params
: Type Ident nextParams
|
;
nextParams
: ',' Type Ident nextParams
|
;
block
: '{' var_decls statements '}'
;
var_decls
: var_decls var_decl
|
;
var_decl
: Type Ident ';'
;
statements
: statement statements
|
;
statement
: location eqOp expr ';'
| If '(' expr ')' block
| If '(' expr ')' block Else block
| While '(' expr ')' statement
| Switch expr '{' cases '}'
| Ret ';'
| Ret '(' expr ')' ';'
| Brk ';'
| Cnt ';'
| block
| methodCall ';'
;
cases
: Case literal ':' statements cases
| Case literal ':' statements
;
methodCall
: Ident '(' args ')'
| Callout '(' Str calloutArgs ')'
;
args
: someArgs
|
;
someArgs
: someArgs ',' expr
| expr
;
calloutArgs
: calloutArgs ',' expr
| calloutArgs ',' Str
|
;
expr
: literal
| location
| '(' expr ')'
| SubOp expr
| '!' expr
| expr AddOp expr
| expr MulDiv expr
| expr SubOp expr
| expr RelOp expr
| expr AndOp expr
| expr OrOp expr
| methodCall
;
location
:Ident
| Ident '[' expr ']'
;
num
: DecNum
| HexNum
;
literal
: num
| Char
| BoolLit
;
eqOp
: '='
| AssignOp
;
//-----------------------------------------------------------------------------------------------------------
fragment Delim
: ' '
| '\t'
| '\n'
;
fragment Letter
: [a-zA-Z]
;
fragment Digit
: [0-9]
;
fragment HexDigit
: Digit
| [a-f]
| [A-F]
;
fragment Alpha
: Letter
| '_'
;
fragment AlphaNum
: Alpha
| Digit
;
WhiteSpace
: Delim+ -> skip
;
Char
: '\'' ~('\\') '\''
| '\'\\' . '\''
;
Str
:'"' ((~('\\' | '"')) | ('\\'.))* '"'
;
Class
: 'class'
;
Program
: 'Program'
;
Void
: 'void'
;
If
: 'if'
;
Else
: 'else'
;
While
: 'while'
;
Switch
: 'switch'
;
Case
: 'case'
;
Ret
: 'return'
;
Brk
: 'break'
;
Cnt
: 'continue'
;
Callout
: 'callout'
;
DecNum
: Digit+
;
HexNum
: '0x'HexDigit+
;
BoolLit
: 'true'
| 'false'
;
Type
: 'int'
| 'boolean'
;
Ident
: Alpha AlphaNum*
;
RelOp
: '<='
| '>='
| '<'
| '>'
| '=='
| '!='
;
AssignOp
: '+='
| '-='
;
MulDiv
: '*'
| '/'
| '%'
;
AddOp
: '+'
;
SubOp
: '-'
;
AndOp
: '&&'
;
OrOp
: '||'
;
И, в принципе, нам нужно сгенерировать промежуточный код с использованием синтаксически направленной трансляции.Насколько я знаю, это означает, что мы должны добавить семантические правила к грамматике синтаксического анализатора.Нам нужно взять сгенерированный вывод и инкапсулировать его в файлы .csv.
Итак, у нас есть три файла: symbols.csv, symtable.csv и инструкция.csv
В символах.csv формат каждой строки:
int id; //serial no. of symbol, unique
int tabid; //id no. of symbol table
string name; //symbol name
enum types {INT, CHAR, BOOL, STR, VOID, LABEL, INVALID} ty; //symbol type
enum scope {GLOBAL, LOCAL, CONST, INVALID} sc; //symbol scope
boolean isArray; //is it an array variable
int arrSize; //array size, if applicable
boolean isInited; //is initialized
union initVal {
int i;
boolean b;
} in; //initial value, if applicable
В symtable.csv формат каждой строки имеет следующий вид:
int id; //symbol table serial no., unique
int parent; //parent symbol table serial no.
В инструкции .csv формат каждой строки имеет вид:
int id; //serial no., unique
int res; //serial no. of result symbol
enum opcode {ADD, SUB, MUL, DIV, NEG, READ, WRITE, ASSIGN, GOTO, LT, GT, LE, GE, EQ, NE, PARAM, CALL, RET, LABEL} opc; //operation type
int op1; //serial no. of first operand symbol
int op2; //serial no. of second operand symbol
В качестве примера, скажем, мывведите:
class Program {
int x;
int y, z;
int w = 0;
void main (int n) {
int a;
a = 0;
while (a < n) {
int n;
n = a + 1;
a = n;
}
callout("printf", "n = %d\n", n);
return n;
}
}
symbols.csv должен выглядеть следующим образом:
0, 0, x, INT, GLOBAL, false, 0, false, 0,
1, 0, y, INT, GLOBAL, false, 0, false, 0,
2, 0, z, INT, GLOBAL, false, 0, false, 0,
3, 0, 0, INT, CONST, false, 0, false, 0,
4, 0, w, INT, GLOBAL, false, 0, true, 0,
5, 0, main, LABEL, GLOBAL, false, 0, false, 0,
6, 1, n, INT, LOCAL, false, 0, false, 0,
7, 1, a, INT, LOCAL, false, 0, false, 0,
8, 1, 0, INT, CONST, false, 0, false, 0,
9, 2, n, INT, LOCAL, false, 0, false, 0,
10, 2, 1, INT, CONST, false, 0, false, 0,
11, 1, "printf", STR, CONST, false, 0, false, 0,
12, 1, "n = %d\n", STR, CONST, false, 0, false, 0,
13, 1, 2, INT, CONST, false, 0, false, 0,
symtables.csv должен выглядеть следующим образом:
0, -1,
1, 0,
2, 1,
инструкция.csvдолжно выглядеть так:
0, 4, ASSIGN, 3, -1, #w = 0
1, 5, LABEL, -1, -1, #main:
2, 7, ASSIGN, 8, -1, #a = 0
3, 5, LT, 7, 6, #if a<n goto 5
4, 8, GE, 7, 6, #iffalse a<n goto 8
5, 9, ADD, 7, 10, #n = a + 1
6, 7, ASSIGN, 9, -1, #a = n
7, 2, GOTO, -1, -1, #goto 3
8, -1, PARAM, 12, -1, #"n = %d\n"
9, -1, PARAM, 6, -1, #n
10, -1, CALL, 11, 13, #callout("printf", "n = %d\n", n);
11, -1, RET, 6, -1, # return n
Проще говоря, я не совсем уверен, с чего начать.Я понимаю, что должен добавить семантические правила в мою грамматику синтаксического анализатора, чтобы иметь возможность выводить результаты, подобные тем, которые я ранее указывал.Кроме того, я провел собственное исследование и обнаружил, что должен создавать классы в java для своих символов, symtable и symstack.Я очень новичок в ANTLR и был бы признателен, если бы кто-то, имеющий опыт в ANTLR, мог указать мне правильное направление.
Заранее благодарю за любую помощь.
PS Мои лексеры и парсер основаныот крошечного C-подобного языка, который размещен ниже.
Tiny C-Like Language:
program
:'class Program {'field_decl* method_decl*'}'
field_decl
: type (id | id'['int_literal']') ( ',' id | id'['int_literal']')*';'
| type id '=' literal ';'
method_decl
: (type | 'void') id'('( (type id) ( ','type id)*)? ')'block
block
: '{'var_decl* statement*'}'
var_decl
: type id(','id)* ';'
type
: 'int'
| 'boolean'
statement
: location assign_op expr';'
| method_call';'
| 'if ('expr')' block ('else' block )?
| 'switch' expr '{'('case' literal ':' statement*)+'}'
| 'while (' expr ')' statement
| 'return' ( expr )? ';'
| 'break ;'
| 'continue ;'
| block
assign_op
: '='
| '+='
| '-='
method_call
: method_name '(' (expr ( ',' expr )*)? ')'
| 'callout (' string_literal ( ',' callout_arg )* ')'
method_name
: id
location
: id
| id '[' expr ']'
expr
: location
| method_call
| literal
| expr bin_op expr
| '-' expr
| '!' expr
| '(' expr ')'
callout_arg
: expr
| string_literal
bin_op
: arith_op
| rel_op
| eq_op
| cond_op
arith_op
: '+'
| '-'
| '*'
| '/'
| '%'
rel_op
: '<'
| '>'
| '<='
| '>='
eq_op
: '=='
| '!='
cond_op
: '&&'
| '||'
literal
: int_literal
| char_literal
| bool_literal
id
: alpha alpha_num*
alpha
: ['a'-'z''A'-'Z''_']
alpha_num
: alpha
| digit
digit
: ['0'-'9']
hex_digit
: digit
| ['a'-'f''A'-'F']
int_literal
: decimal_literal
| hex_literal
decimal_literal
: digit+
hex_literal
: '0x' hex_digit+
bool_literal
: 'true'
| 'false'
char_literal
: '‘'char'’'
string_literal
: '“'char*'”'