我对|
表达有严重的问题。
我的语法包含这样的表达式。
...ifelse : 'IF' condition 'THEN' dosomething+ 'ENDIF'
...dosomething : assign | print | input;
但dosomething
变得不变。例如:
IF a > 3 THEN
PRINT "HEllo"
b = a
ENDIF
所以首先dosomething
是print
,语法无法读取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
答案 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
语句很好,如果你需要它可以任意嵌套。这是运行关键域特定语言的生产代码。