2012-05-29 5 views
1

Я использую ANTLR и следующую грамматику:QuickBasic Грамматика используя ANTLR

grammar QuickBasic; 

options 
{ 
    language = 'CSharp2'; 
    output = AST; 
} 

parse 
    : block EOF 
    ; 

block 
    : (labelStatement | labeledStatement | statement)* 
    ; 

labelStatement 
    : label ':' -> ^(label) 
    ; 

labeledStatement 
    : label statement -> ^(label statement) 
    ; 

statement 
    : assignment 
    ; 

assignment 
    : IDENTIFIER '=' value -> ^('=' IDENTIFIER value) 
    ; 

value 
    : (IDENTIFIER | constant) 
    ; 

constant 
    : (STRING | INTEGER | REAL) 
    ; 

label 
    : (ALPHANUMERIC)+ 
    ; 

IDENTIFIER 
    : LETTER (ALPHANUMERIC)* 
    ; 

REAL 
    : (INTEGER '.' NATURAL) 
    ; 

INTEGER 
    : ('-')? NATURAL 
    ; 

SPACE 
    : (' ' | '\t' | '\r' | '\n' | '\u000C') {Skip();} 
    ; 

STRING 
    : '"' ('""' | ~'"')* '"' 
    ; 

fragment NATURAL 
    : (DIGIT)+ 
    ; 

fragment ALPHANUMERIC 
    : (DIGIT | LETTER) 
    ; 

fragment DIGIT 
    : '0'..'9' 
    ; 

fragment LETTER 
    : ('a'..'z' | 'A'..'Z') 
    ; 

С этим, я пытаюсь разобрать на следующие файлы:

PI = 3.141592 
CALC: 
100 A = 1 

Что происходит дальше, что линия «CALC:» должен быть меткой, но он пытается разобрать как оператор и дает мне ошибку, говорящий о несоответствующем вводе ':' expecting '='.

ответ

2

Ваше label правило является неправильным:

label 
    : (ALPHANUMERIC)+ 
    ; 

ALPHANUMERIC, потому что это fragment- lexer, он может использоваться только другими правилами lexer, никогда в правилах парсера. Ваш лексер будет производить только следующие токены: IDENTIFIER, INTEGER, REAL и STRING (плюс литеральные жетоны в правилах анализатора, такие как '.' и т. Д.): Это те правила, которые вы можете использовать только в правилах вашего парсера.

Кроме того, вы должны создавать только AST, у которых есть единственный корень . Вы пытаетесь создать корень как для labelStatement, так и для labeledStatement, что не позволит отличить его от других правил синтаксического анализа: создание ходунки дерева (или хорды ANTLR или вашего собственного ходока дерева), имеющих проблемы, когда они сталкиваются с корнем таких АСТ. Гораздо лучше создать (мнимая) LABEL и LABELED_STAT лексемы сделать их корень вашего AST:

... 

tokens 
{ 
    LABEL; 
    LABELED_STAT; 
} 

parse 
    : block EOF 
    ; 

... 

labelStatement 
    : label ':' -> ^(LABEL label) 
    ; 

labeledStatement 
    : label statement -> ^(LABELED_STAT label statement) 
    ; 

... 

label 
    : IDENTIFIER 
    | INTEGER 
    ; 

Это создаст следующую AST:

enter image description here

+0

ТОЧНО! Спасибо, Барт! –

+0

Добро пожаловать @ JonathasCosta. –

0

попробуйте использовать строчные пропустить() вместо Skip() и что-то вроде этого, чтобы позволить несколько пробелов

SPACE 
    : (' ' | '\t' | '\u000C' | '\n' | '\r')+ {skip();} 
    ; 
+0

Я думал, "пропустить()" был просто метод в базовом классе «Lexer» для java ... поскольку я использую C#, метод «Skip()». Это верно? –

+0

Нет, 'Skip()' вместо 'skip()' и добавление '+' в 'SPACE' правило не повлияет. (@JonathasCosta, да, вы правы). –

Смежные вопросы