Методические указания (1114907), страница 15
Текст из файла (страница 15)
Рис. 5.8. Представление оптимизированного промежуточного кода в виде синтаксического дерева, преобразованного из троек.
-
Косвенные тройки -> синтаксическое дерево
Вид данного синтаксического дерева совпадает с тем, что изображено на рис. 5.8.
-
Четверки -> даг
Рис. 5.8. Представление оптимизированного промежуточного кода в виде дага, преобразованного из четверок.
-
Тройки -> даг
-
Косвенные тройки -> даг
Вид дага совпадает как для троек, так и для косвенных троек в силу специфики собственно дага и его представления в трехадресном коде.
-
Построим формальную КС-грамматику, которая задает похожие фрагменты исходного кода, при помощи среды antlrworks.
grammar Task5Grammar;
options {
language = Java;
}
ID : ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_')*
;
DIGIT : '0'..'9'+
;
STRING : '"' ~'"'* '"'
;
WS : ( ' '
| '\t'
| '\r'
| '\n'
) {$channel=HIDDEN;}
;
type : 'int' | 'char[]'
;
assign
: ID '=' (expression)
;
assign_operator
: assign ';'
;
expression
: ID |
STRING |
DIGIT |
arifmetic_expression |
incrementation |
function_call |
array_element |
getting_address
;
arifmetic_operand
: ID |
DIGIT
;
arifmetic_expression
: arifmetic_operand arifmetic_sign arifmetic_operand
;
arifmetic_sign
: ('+' | '*')
;
incrementation
: ID '++'
;
array_element
: ID '[' expression ']'
;
getting_address
: '&' ID
;
function_call
: ID '(' parametres ')'
;
parametres
: (expression (',' expression)*)?
;
variable_declaration
: type (ID | assign) (',' (ID | assign))* ';'
;
for_operator
: 'for' '(' type? assign ';' logical_condition ';' expression ')' '{'
operator+
'}'
;
function_call_operator
: function_call ';'
;
logical_condition
: expression logical_link expression
;
logical_link
: '==' | '!=' | '>' | '<' | '>=' | '<='
;
operator : variable_declaration | assign_operator | for_operator | function_call_operator
;
program : (operator)+
;
-
Построение атрибутивной грамматики с семантическими проверками и генерацией целевого кода в указанном формате.
-
Для синтаксического дерева.
-
grammar Task5Grammar;
options {
language = Java;
}
@members {
protected NamesTable names = new NamesTable();
protected ArrayList<String> errors = new ArrayList<String>();
protected ArrayList<String> instructions = new ArrayList<String>();
protected ArrayList<String> constants = new ArrayList<String>();
protected int instructionNumber = 0;
protected String program = "";
public static void main(String[] args) throws Exception {
Task5GrammarLexer lex = new Task5GrammarLexer(new ANTLRFileStream("test.txt"));
Task5GrammarParser parser = new Task5GrammarParser(new CommonTokenStream(lex));
parser.program();
if (! parser.errors.isEmpty()) {
System.out.println("Found " + parser.errors.size() + " errors:");
for (String m : parser.errors) {
System.out.println(m);
}
}
else {
System.out.println("Compiled successfully");
System.out.println("Constants:");
int i = 1;
for (String m : parser.constants) {
System.out.println("D0" + i + " " + m);
i++;
}
System.out.println("program " + parser.program);
for (String m : parser.instructions) {
System.out.println(m);
}
}
}
public String getErrorHeader(RecognitionException e) {
return "line "+e.line+":";
}
public void emitErrorMessage(String msg) {
errors.add(msg);
}
public int getInstructionNumber() {
instructionNumber++;
return instructionNumber - 1;
}
}
ID : ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_')*
;
DIGIT : '0'..'9'+
;
STRING : '"' ~'"'* '"'
;
WS : ( ' '
| '\t'
| '\r'
| '\n'
) {$channel=HIDDEN;}
;
type
: 'int' | 'char[]'
;
assign returns [String idName, int idLine, String expressionType, int instructionNumber]
: ID '=' (expression) {
$idName = $ID.text;
$idLine = $ID.line;
$expressionType = $expression.expressionType;
$instructionNumber = getInstructionNumber();
if ($expression.expressionClass.equals("id") ||
$expression.expressionClass.equals("const_string") ||
$expression.expressionClass.equals("const_int")) {
if ($expression.expressionClass.equals("const_string")) {
//constants.add($expression.text);
instructions.add("(" + $instructionNumber + ") " + "ID" + " " + $ID.text);
$instructionNumber = getInstructionNumber();
instructions.add("(" + $instructionNumber + ") " + "assign" + " " + "(" + ($instructionNumber - 1) + ") " + "(" + $expression.instructionNumber + ")");
}
else {
instructions.add("(" + $instructionNumber + ") " + "ID" + " " + $ID.text);
$instructionNumber = getInstructionNumber();
instructions.add("(" + $instructionNumber + ") " + "assign" + " " + "(" + ($instructionNumber - 1) + ") " + "(" + $expression.instructionNumber + ")");
}
}
else {
instructions.add("(" + $instructionNumber + ") " + "ID" + " " + $ID.text);
$instructionNumber = getInstructionNumber();
instructions.add("(" + $instructionNumber + ") " + "assign" + " " + "(" + ($instructionNumber - 1) + ") (" + $expression.instructionNumber + ")");
}
}
;
assign_operator returns [int instructionNumber]
: assign ';' {
if (!names.isExist($assign.idName)) {
errors.add("line " + $assign.idLine + ": name " + $assign.idName + " is not declarated");
}
else {
if (!$assign.expressionType.equals(names.get($assign.idName).getType())) {
errors.add("line " + $assign.idLine + ": name " + $assign.idName + " type is mismatched");
}
else {
$instructionNumber = $assign.instructionNumber;
}
}
}
;
expression returns [String expressionType, String expressionClass, int instructionNumber]
: ID {
if (!names.isExist($ID.text)) {
errors.add("line " + $ID.line + ": name " + $ID.text + " is not declarated");
}
else {
$expressionType = names.get($ID.text).getType();
$expressionClass = "id";
$instructionNumber = getInstructionNumber();
instructions.add("(" + $instructionNumber + ") " + "ID" + " " + $ID.text);
}
}
| STRING {
$expressionType = "char[]";
$expressionClass = "const_string";
$instructionNumber = getInstructionNumber();
constants.add($STRING.text);
instructions.add("(" + $instructionNumber + ") " + "String" + " D0" + constants.size());
}
| DIGIT {
$expressionType = "int";
$expressionClass = "const_int";
$instructionNumber = getInstructionNumber();
instructions.add("(" + $instructionNumber + ") " + "Number" + " " + $DIGIT.text);
}
| arifmetic_expression {
$expressionType = "int";
$expressionClass = "arifmetic_expression";
$instructionNumber = $arifmetic_expression.instructionNumber;
}
| function_call[false] {
$expressionType = $function_call.resultType;
$expressionClass = "function_call";
$instructionNumber = $function_call.instructionNumber;
}
| array_element {
$expressionType = "int";
$expressionClass = "array_element";
$instructionNumber = $array_element.instructionNumber;
}
| getting_address {
$expressionType = "int";
$expressionClass = "getting_address";
$instructionNumber = $getting_address.instructionNumber;
}
;
arifmetic_operand returns [int instructionNumber]
: ID {
if (!names.isExist($ID.text)) {
errors.add("line " + $ID.line + ": name " + $ID.text + " is not declarated");
}
else {
if (!names.get($ID.text).getType().equals("int")) {
errors.add("line " + $ID.line + ": name " + $ID.text + " type mismatched");
}
else {
$instructionNumber = getInstructionNumber();
instructions.add("(" + $instructionNumber + ") " + "ID" + " " + $ID.text);
}
}
}
| DIGIT {
$instructionNumber = getInstructionNumber();
instructions.add("(" + $instructionNumber + ") " + "Number" + " " + $DIGIT.text);
}
;
arifmetic_expression returns[int instructionNumber]
: operandFirst = arifmetic_operand arifmetic_sign operandSecond = arifmetic_operand {
$instructionNumber = getInstructionNumber();
instructions.add("(" + $instructionNumber + ") " + $arifmetic_sign.text + " " + "(" + $operandFirst.instructionNumber + ")" + " " + "(" + $operandSecond.instructionNumber + ")");
}
;
arifmetic_sign
: ('+' | '-' | '*' | '/')
;
incrementation returns [String idName, int instructionNumber]
: ID '++' {
if (!names.isExist($ID.text)) {
errors.add("line " + $ID.line + ": name " + $ID.text + " is not declarated");
}
else {
if (!names.get($ID.text).getType().equals("int")) {
errors.add("line " + $ID.line + ": name " + $ID.text + " type mismatched");
}
else {
$idName = $ID.text;
$instructionNumber = getInstructionNumber();
instructions.add("(" + $instructionNumber + ") " + "ID" + " " + $ID.text);
$instructionNumber = getInstructionNumber();
instructions.add("(" + $instructionNumber + ") " + "++" + " " + "(" + ($instructionNumber - 1) + ")" );
}
}
}
;
array_element returns [int instructionNumber]
: ID '[' expression ']' {
if (!names.isExist($ID.text)) {
errors.add("line " + $ID.line + ": name " + $ID.text + " is not declarated");
}
else {
if (!names.get($ID.text).getType().equals("char[]")) {
errors.add("line " + $ID.line + ": name " + $ID.text + " type mismatched");
}
}
if (!$expression.expressionType.equals("int")) {