ANTLR'或'正则表达式

时间:2017-07-13 13:00:34

标签: parsing antlr grammar

我对|表达有严重的问题。

我的语法包含这样的表达式。

...ifelse : 'IF' condition 'THEN' dosomething+ 'ENDIF'
...dosomething : assign | print | input;

dosomething变得不变。例如:

IF a > 3 THEN
PRINT "HEllo"
b = a
ENDIF

所以首先dosomethingprint,语法无法读取assing, input

如果语句变为这样,那么它的工作正确

IF a > 3 THEN
PRINT "HEllo"
PRINT myName
ENDIF

所以我的意思是'或'( | | )+表达式变成与第一次出现的表达式相同的常量。

grammar hellog;

prog : command+;

command : maincommand
        | expressioncommand
        | flowcommand
        ;
//main
maincommand : printcommand
            | inputcommand
            ;

printcommand : 'PRINT' (IDINT | IDSTR | STRING) NL
             | 'PRINT' (IDINT | IDSTR | STRING) (',' (IDINT | IDSTR | STRING))* NL
             ;
inputcommand : 'INPUT' (IDINT | IDSTR) NL
             | 'INPUT' STRING? (IDINT | IDSTR) NL
             ;

//expression
expressioncommand : intexpression
                  | strexpression
                  ;
intexpression : IDINT '=' (IDINT | INT) NL
              | IDINT '=' (IDINT | INT) (OPERATORMATH (IDINT | INT))* NL
              ;
strexpression : IDSTR '=' (IDSTR | STRING) NL
              | IDSTR '=' (IDSTR | STRING) ('+' (IDSTR | STRING))* NL
              ;
//flow
flowcommand : ifelseflow
            | whileflow
            ;

ifelseflow : 'IF' conditionflow 'THEN' NL dosomething+ ('ELSEIF' conditionflow 'THEN' NL dosomething+)* ('ELSE' NL dosomething+)? 'ENDIF' NL;
whileflow : 'WHILE' conditionflow NL (dosomething)+ 'WEND' NL;
dosomething : command;
conditionflow : (INT | IDINT) OPERATORBOOL (INT | IDINT)
              | (STRING | IDSTR) '=' (STRING | IDSTR)
              ;

INT : [0-9]+;
STRING : '"' .*? '"';
IDINT : [a-zA-Z]+;
IDSTR : [a-zA-Z]+'$';
NL : '\n';
WS : [ \t\r]+ -> skip;
OPERATORMATH : '+' | '-' | '*' | '/';
OPERATORBOOL : '=' | '>' | '<' | '>=' | '<=';

我只需要一个语法来运行这些表达式:

PRINT "Your name"
INPUT name
PRINT "HELLO" name

a = 6
IF a > 3 THEN
PRINT a
a = a -1
END IF

WHILE b = 3
PRINT b
a = b
WEND

1 个答案:

答案 0 :(得分:0)

我的回答并不完全是关于|替代方案,但请继续阅读,因为像您一样,我发现在类似BASIC的语言中实现if..else结构是一个真正的实施挑战。我在网上找到了一些好的资源。当我做对了,很多很多问题一下子消失了,刚刚开始工作。请看一下我的语法剪辑:

ifstmt
:   IF condition_block (ELSE IF condition_block)* (ELSE stmt_block)?
;

condition_block
:   expr stmt_block
;

stmt_block
:   OBRACE statement+ CBRACE
|   statement
;

我的实现(在C#访客模式中):

 public override MuValue VisitIfstmt(LISBASICParser.IfstmtContext context)
    {
        LISBASICParser.Condition_blockContext[] conditions = context.condition_block();
        bool evaluatedBlock = false;
        foreach (LISBASICParser.Condition_blockContext condition in conditions)
        {
            MuValue evaluated = Visit(condition.expr());
            if (evaluated.AsBoolean())
            {
                evaluatedBlock = true;
                Visit(condition.stmt_block());
                break;
            }
        }
        if (!evaluatedBlock && context.stmt_block() != null)
        {
            Visit(context.stmt_block());
        }
        return MuValue.Void;
    }

借鉴了巴特·基尔斯对他的穆示范语言的出色表现。他的那个项目中有很多好点子。它真的向我展示了光和这个代码我已经显示处理if语句很好,如果你需要它可以任意嵌套。这是运行关键域特定语言的生产代码。