我试图找到一种在Scala领域集成antlr解析器的方法。
我已经尝试过使用scala编码的访问者来从解析树中构建scala对象,但是有一个统一的返回类型的限制是不行的。
所以我采取了尝试,并决定使用scala类的java接口直接从解析器操作构建scala对象。
这篇博文非常有用:
http://blog.akquinet.de/2011/07/20/integrating-scala-components-in-a-java-application/
这是我获得的:
scala AST DSL
package toylang.ast
trait TypeExpr
case object IntType extends TypeExpr
case object BoolType extends TypeExpr
trait Expr
case class Ident(name: String) extends Expr
case class IntNum(repr: String) extends Expr
case object True extends Expr
case object False extends Expr
case class Plus(e: Expr) extends Expr
case class Minus(e: Expr) extends Expr
case class Add(l: Expr, r: Expr) extends Expr
case class Sub(l: Expr, r: Expr) extends Expr
case class Mul(l: Expr, r: Expr) extends Expr
case class Div(l: Expr, r: Expr) extends Expr
case class Pow(e: Expr, exponent: Expr) extends Expr
case class Not(e: Expr) extends Expr
case class And(l: Expr, r: Expr) extends Expr
case class Or(l: Expr, r: Expr) extends Expr
case class Implies(l: Expr, r: Expr) extends Expr
case class Ite(c: Expr, t: Expr, eif: List[Elsif], e:Expr) extends Expr
case class Elsif(c: Expr, t: Expr)
case class Neq(l: Expr, r: Expr) extends Expr
case class Eq(l: Expr, r: Expr) extends Expr
case class Lt(l: Expr, r: Expr) extends Expr
case class Le(l: Expr, r: Expr) extends Expr
case class Gt(l: Expr, r: Expr) extends Expr
case class Ge(l: Expr, r: Expr) extends Expr
trait Stmt
case class DefStmt(id: Ident, t: TypeExpr, e: Expr) extends Stmt
使用java动作调用scala构造函数的antlr语法
grammar ToyLang;
// lexer customized header
@lexer::header{
package toylang.parser.antlr;
}
// parser customized header
@parser::header{
package toylang.parser.antlr;
import toylang.ast.*;
import java.util.List;
import java.util.ArrayList;
import utils.Fun;
import utils.Conv;
}
@parser::members {
// a class which extracts an object from a context an can be mapped over a java list.
Fun defStmtMap = new Fun<DefStmtContext, Stmt> () {
public Stmt apply(DefStmtContext ctx) {
return ctx.result;
}
};
// a class which extracts an object from a context an can be mapped over a java list.
Fun elsifMap = new Fun<ElsifContext, Elsif> () {
public Elsif apply(ElsifContext ctx) {
return ctx.result;
}
};
}
program returns [scala.collection.immutable.List<Stmt> result]
: sl+=defStmt sl+=defStmt* EOF {
$result = Conv.scalaList(Conv.map($sl, defStmtMap));
}
;
type returns[TypeExpr result]
: 'int' { $result = IntType$.MODULE$; }
| 'bool' { $result = IntType$.MODULE$; }
;
defStmt returns[Stmt result]
: id=ident ':' t=type op=DEFINE e=expr ';' {
$result = DefStmt$.MODULE$.apply($id.ctx.result, $t.ctx.result, $e.ctx.result);
}
;
expr returns[Expr result]
: lit=TRUE
{ $result = True$.MODULE$; }
| lit=FALSE
{ $result = False$.MODULE$; }
| lit=INT_LIT
{ $result = IntNum$.MODULE$.apply($lit.text); }
| id=ident
{ $result = $id.ctx.result; }
| op='(' e=expr ')'
{ $result = $e.ctx.result; }
| IF c=expr THEN t=expr ei+=elsif* ELSE e=expr
{
scala.collection.immutable.List<Elsif> l = Conv.scalaList(Conv.map($ei, elsifMap));
$result = Ite$.MODULE$.apply($c.ctx.result, $t.ctx.result, l, $e.ctx.result);
}
| op=(ADD|SUB) e=expr
{
switch($op.type) {
case ADD : $result = Plus$.MODULE$.apply($e.ctx.result); break;
case SUB : $result = Minus$.MODULE$.apply($e.ctx.result); break;
}
}
|<assoc=right> l=expr op=CARRET r=expr
{ $result = Pow$.MODULE$.apply($l.ctx.result, $r.ctx.result); }
|<assoc=left> l=expr op=(STAR|SLASH) r=expr
{
switch($op.type) {
case STAR : $result = Mul$.MODULE$.apply($l.ctx.result, $r.ctx.result); break;
case SLASH : $result = Div$.MODULE$.apply($l.ctx.result, $r.ctx.result); break;
}
}
|<assoc=left> l=expr op=(ADD|SUB) r=expr
{
switch($op.type) {
case ADD : $result = Add$.MODULE$.apply($l.ctx.result, $r.ctx.result); break;
case SUB : $result = Sub$.MODULE$.apply($l.ctx.result, $r.ctx.result); break;
}
}
| l=expr op=(NEQ|EQ|LT|LE|GT|GE) r=expr
{
switch($op.type) {
case NEQ : $result = Neq$.MODULE$.apply($l.ctx.result, $r.ctx.result); break;
case EQ : $result = Eq$.MODULE$.apply($l.ctx.result, $r.ctx.result); break;
case LT : $result = Lt$.MODULE$.apply($l.ctx.result, $r.ctx.result); break;
case LE : $result = Le$.MODULE$.apply($l.ctx.result, $r.ctx.result); break;
case GT : $result = Gt$.MODULE$.apply($l.ctx.result, $r.ctx.result); break;
case GE : $result = Ge$.MODULE$.apply($l.ctx.result, $r.ctx.result); break;
}
}
| op=NOT e=expr
{ $result = Not$.MODULE$.apply($e.ctx.result); }
|<assoc=left> l=expr op=AND r=expr
{ $result = And$.MODULE$.apply($l.ctx.result, $r.ctx.result); }
|<assoc=left> l=expr op=OR r=expr
{ $result = Or$.MODULE$.apply($l.ctx.result, $r.ctx.result); }
|<assoc=left> l=expr op=IMPLIES r=expr
{ $result = Implies$.MODULE$.apply($l.ctx.result, $r.ctx.result); }
;
elsif returns[Elsif result]
: op=ELSIF c=expr THEN t=expr
{
$result = Elsif$.MODULE$.apply($c.ctx.result, $t.ctx.result);
}
;
ident returns [Ident result]
: IDENT { $result = Ident$.MODULE$.apply($IDENT.text); }
;
LT: '<' ;
LE: '<=' ;
GT: '>' ;
GE: '>=' ;
EQ: '=' ;
NEQ: '!=' ;
ADD: '+';
AND: 'and';
DEFINE: ':=';
CARRET: '^';
ELSE: 'else';
ELSIF: 'elsif';
FALSE: 'false';
IF: 'if';
IMPLIES: 'implies';
KW_BOOL: 'bool';
KW_INT: 'int';
NOT: 'not';
OR: 'or';
SLASH: '*';
STAR: '*';
SUB: '-';
THEN: 'then';
TRUE: 'true';
INT_LIT
:'0'
|[1-9][0-9]*
;
IDENT:[_a-zA-Z][_a-zA-Z0-9]*;
WS: [ \t\f\r\n]+ -> skip;
//NL: '\r'? \n;
最后两个java实用程序类,Conv和Fun,Conv包含将java列表转换为类型很好的scala列表的代码,Fun是在转换为scala列表之前映射到java列表的操作的接口
package utils;
import java.util.List;
import java.util.ArrayList;
public final class Conv<A, B> {
public static <T> scala.collection.immutable.List<T> scalaList(List<T> javaList) {
return scala.collection.JavaConversions.iterableAsScalaIterable(javaList).toList();
}
public static <A,B> List<B> map(List<A> from, Fun<A,B> convert) {
ArrayList<B> res = new ArrayList<B>();
for (A fromElem : from) {
res.add(convert.apply(fromElem));
}
return res;
}
}
package utils;
public interface Fun<A, B> {
B apply(A input);
}
调用antlr解析器的scala代码:
package toylang.parser
import org.antlr.v4.runtime._
import org.antlr.v4.runtime.tree._
import org.stringtemplate.v4._
import toylang.parser.antlr._
import java.io.FileInputStream
import scala.collection.JavaConverters._
class Parser( arg: String ) {
val input = new ANTLRInputStream(new FileInputStream(arg))
val lexer = new ToyLangLexer(input)
val tokens = new CommonTokenStream(lexer)
val parser = new ToyLangParser(tokens)
val prog = parser.program
println (prog.result)
}
欢迎任何改进extract-results-from-contex-java-to-scala列表转换的想法。使它完全通用将是很好的,可能使用java反射API。理想情况下,我想用一个语句来说:提取字段名为&#39; foo&#39;来自此列表的每个antlr规则上下文对象(或标记),并将结果转换为scala列表。
我已经在网上四处看了一眼,并没有发现如何做到这一点。
此致
答案 0 :(得分:1)
答案一直在我的眼前,我太盲目无法看到它:听众。
使用locals定义更新语法,以便可以存储scala对象:
grammar ToyLang2;
@lexer::header{
package toylang.parser.antlr;
}
@parser::header{
package toylang.parser.antlr;
import toylang.ast.*; // import scala ast symbols
}
program
locals [scala.collection.immutable.List<Stmt> result]
: sl+=defStmt sl+=defStmt* EOF
;
type
locals [TypeExpr result]
: 'int' # IntType
| 'bool' # BoolType
;
defStmt
locals[Stmt result]
: id=ident ':' t=type d=def? ';'
;
def
locals [Expr result]
: op=DEFINE e=expr
;
expr
locals[Expr result]
: e=boolNum #BoolNumExpr
| e=intNum #IntNumxpr
| e=ident #IdentExpr
| op='(' e=expr ')' #ParenExpr
| IF c=expr THEN t=expr ei+=elsif* ELSE e=expr #IteExpr
| op=(ADD|SUB) e=expr #UnopArithExpr
|<assoc=right> l=expr op=CARRET r=expr #PowerExpr
|<assoc=left> l=expr op=(STAR|SLASH) r=expr #MulDivExpr
|<assoc=left> l=expr op=(ADD|SUB) r=expr #AddSubExpr
| l=expr op=(NEQ|EQ|LT|LE|GT|GE) r=expr #RelExpr
| op=NOT e=expr #NotExpr
|<assoc=left> l=expr op=AND r=expr #AndExpr
|<assoc=left> l=expr op=OR r=expr #OrExpr
|<assoc=left> l=expr op=IMPLIES r=expr #ImpliesExpr
;
elsif
locals [Elsif result]
: op=ELSIF c=expr THEN t=expr
;
ident
locals [Ident result]
: id=IDENT
;
intNum
locals [IntNum result]
: num=INT_NUM
;
boolNum
locals [BoolNum result]
: num=(TRUE | FALSE)
;
LT: '<' ;
LE: '<=' ;
GT: '>' ;
GE: '>=' ;
EQ: '=' ;
NEQ: '!=' ;
ADD: '+';
AND: 'and';
DEFINE: ':=';
CARRET: '^';
ELSE: 'else';
ELSIF: 'elsif';
FALSE: 'false';
IF: 'if';
IMPLIES: 'implies';
KW_BOOL: 'bool';
KW_INT: 'int';
NOT: 'not';
OR: 'or';
SLASH: '*';
STAR: '*';
SUB: '-';
THEN: 'then';
TRUE: 'true';
INT_NUM :'0' |[1-9][0-9]* ;
IDENT:[_a-zA-Z][_a-zA-Z0-9]* ;
WS: [ \t\f\r\n]+ -> skip;
//NL: '\r'? \n;
还有一个Scala听众:
package toylang.parser.antlr
import toylang.ast._
import scala.collection.JavaConversions._
class Listener extends ToyLang2BaseListener {
// stores the result of a successfull parse
var result: Option[List[Stmt]] = None
override def exitBoolNum(ctx: ToyLang2Parser.BoolNumContext ): Unit = {
ctx.result = BoolNum(ctx.num.getText)
}
override def exitImpliesExpr(ctx: ToyLang2Parser.ImpliesExprContext ): Unit = {
ctx.result = Implies (ctx.l.result, ctx.r.result)
}
override def exitAddSubExpr(ctx: ToyLang2Parser.AddSubExprContext ): Unit = {
import ToyLang2Parser.{ADD, SUB}
ctx.result = ctx.op.getType match {
case ADD => Add(ctx.l.result, ctx.r.result)
case SUB => Sub(ctx.l.result, ctx.r.result)
}
}
override def exitIteExpr(ctx: ToyLang2Parser.IteExprContext ): Unit = {
// using views to avoid creation of intermediate data
val elsifList = ctx.ei.view map { _.result }
ctx.result = Ite(ctx.c.result, ctx.t.result, elsifList.toList, ctx.e.result)
}
override def exitBoolNumExpr(ctx: ToyLang2Parser.BoolNumExprContext ): Unit = {
ctx.result = ctx.e.result
}
override def exitParenExpr(ctx: ToyLang2Parser.ParenExprContext ): Unit = {
ctx.result = ctx.e.result
}
override def exitPowerExpr(ctx: ToyLang2Parser.PowerExprContext ): Unit = {
ctx.result = Pow(ctx.l.result, ctx.r.result)
}
override def exitIntNum(ctx: ToyLang2Parser.IntNumContext ): Unit = {
ctx.result = IntNum(ctx.num.getText)
}
override def exitIdentExpr(ctx: ToyLang2Parser.IdentExprContext ): Unit = {
ctx.result = ctx.e.result
}
override def exitNotExpr(ctx: ToyLang2Parser.NotExprContext ): Unit = {
ctx.result = Not(ctx.e.result)
}
override def exitElsif(ctx: ToyLang2Parser.ElsifContext ): Unit = {
ctx.result = Elsif(ctx.c.result, ctx.t.result)
}
override def exitBoolType(ctx: ToyLang2Parser.BoolTypeContext ): Unit = {
ctx.result = BoolType
}
override def exitIdent(ctx: ToyLang2Parser.IdentContext ): Unit = {
ctx.result = Ident(ctx.id.getText)
}
override def exitAndExpr(ctx: ToyLang2Parser.AndExprContext ): Unit = {
ctx.result = And(ctx.l.result, ctx.r.result)
}
override def exitOrExpr(ctx: ToyLang2Parser.OrExprContext ): Unit = {
ctx.result = Or(ctx.l.result, ctx.r.result)
}
override def exitDef(ctx: ToyLang2Parser.DefContext ): Unit = {
ctx.result = ctx.e.result
}
override def exitProgram(ctx: ToyLang2Parser.ProgramContext ): Unit = {
ctx.result = (ctx.sl.view map { _.result }).toList
result = Some(ctx.result)
}
override def exitIntType(ctx: ToyLang2Parser.IntTypeContext ): Unit = {
ctx.result = IntType
}
override def exitMulDivExpr(ctx: ToyLang2Parser.MulDivExprContext ): Unit = {
import ToyLang2Parser.{STAR,SLASH}
ctx.result = ctx.op.getType match {
case STAR => Mul(ctx.l.result, ctx.r.result)
case SLASH => Div(ctx.l.result, ctx.r.result)
}
}
override def exitUnopArithExpr(ctx: ToyLang2Parser.UnopArithExprContext ): Unit = {
import ToyLang2Parser.{ADD, SUB}
ctx.result = ctx.op.getType match {
case ADD => Plus(ctx.e.result)
case SUB => Minus(ctx.e.result)
}
}
override def exitIntNumxpr(ctx: ToyLang2Parser.IntNumxprContext ): Unit = {
ctx.result = ctx.e.result
}
override def exitDefStmt(ctx: ToyLang2Parser.DefStmtContext ): Unit = {
val d = ctx.d match {
case null => None
case e@_ => Some(e.result)
}
ctx.result = DefStmt(ctx.id.result, ctx.t.result, d)
}
override def exitRelExpr(ctx: ToyLang2Parser.RelExprContext ): Unit = {
import ToyLang2Parser.{NEQ,EQ,LT,LE,GT,GE}
ctx.op.getType match {
case NEQ => Neq(ctx.l.result, ctx.r.result)
case EQ => Eq(ctx.l.result, ctx.r.result)
case LT => Lt(ctx.l.result, ctx.r.result)
case LE => Le(ctx.l.result, ctx.r.result)
case GT => Gt(ctx.l.result, ctx.r.result)
case GE => Ge(ctx.l.result, ctx.r.result)
}
}
}
最后,来自scala的instanciate antlr解析器并注册scala监听器:
package toylang.parser
import toylang.parser.antlr.{Listener, ToyLang2Lexer, ToyLang2Parser}
import org.antlr.v4.runtime.{ANTLRInputStream, CommonTokenStream}
import java.io.FileInputStream
class Parser2( arg: String ) {
val input = new ANTLRInputStream(new FileInputStream(arg))
val lexer = new ToyLang2Lexer(input)
val tokens = new CommonTokenStream(lexer)
val parser = new ToyLang2Parser(tokens)
val listener = new Listener
parser.addParseListener(listener)
val prog = parser.program
println (listener.result)
}
这不可能变得更简单。
答案 1 :(得分:0)
只是为了给你一个抬头,我已经整理了一个hack,能够直接在g4语法中嵌入scala动作。
我修改了ANTLRv4Lexer.g4和ANTLRv4Parser.g4:
https://github.com/antlr/grammars-v4/tree/master/antlr4
允许这样的特殊评论
//! <scala code>
首先在文件中添加以定义scala侦听器的标头
就在定义scala监听器成员的规则列表之前,
并且在规则备选方案之前或之后,为每个备选方案指定进入和退出操作(必须标记)。
基于这种修改过的格式,我开发了一个工具,可以从特殊注释中提取和打包scala监听器的代码。
实际上,带有scala操作的扩展文件如下所示:
//! // scala listener header
//! package toylang.parser.antlr
//! import toylang.ast._
//! import scala.collection.JavaConversions._
grammar ToyLang;
@lexer::header{
package toylang.parser.antlr;
}
@parser::header{
package toylang.parser.antlr;
import toylang.ast.*; // import scala ast symbols
}
//! // scala listener members
//! // stores the result of a successfull parse
//! var result: Option[List[Stmt]] = None
program
locals [scala.collection.immutable.List<Stmt> result]
: sl+=defStmt sl+=defStmt* EOF # ProgramRule
//! // exitAction for alternative
//! ctx.result = (ctx.sl.view map { _.result }).toList
//! result = Some(ctx.result)
;
type
locals [TypeExpr result]
: 'int' # IntType
//! ctx.result = IntType
| 'bool' # BoolType
//! ctx.result = BoolType
;
defStmt
locals[Stmt result]
:
//! // entry action for alternative
//! println("About to parse a statement!")
//!
id=ident ':' t=type d=def? ';' # DefStmtRule
//! // exit action for alternative
//! val d = ctx.d match {
//! case null => None
//! case e@_ => Some(e.result)
//! }
//! ctx.result = DefStmt(ctx.id.result, ctx.t.result, d)
;
def
locals [Expr result]
: op=DEFINE e=expr # DefRule
//! ctx.result = ctx.e.result
;
expr
locals[Expr result]
: e=boolNum # BoolNumExpr
//! ctx.result = ctx.e.result
| e=intNum # IntNumxpr
//! ctx.result = ctx.e.result
| e=ident # IdentExpr
//! ctx.result = ctx.e.result
| op='(' e=expr ')' # ParenExpr
//! ctx.result = ctx.e.result
| op=(ADD|SUB) e=expr # UnopArithExpr
//! import ToyLangParser.{ADD, SUB}
//! val op = ctx.op.getType match {
//! case ADD => Plus
//! case SUB => Minus
//! }
//! ctx.result = op(ctx.e.result)
|<assoc=right> l=expr op=CARRET r=expr # PowerExpr
//! ctx.result = Pow(ctx.l.result, ctx.r.result)
|<assoc=left> l=expr op=(STAR|SLASH) r=expr # MulDivExpr
//! import ToyLangParser.{STAR, SLASH}
//! val op = ctx.op.getType match {
//! case STAR => Mul
//! case SLASH => Div
//! }
//! ctx.result = op(ctx.l.result, ctx.r.result)
|<assoc=left> l=expr op=(ADD|SUB) r=expr # AddSubExpr
//! import ToyLangParser.{ADD, SUB}
//! val op = ctx.op.getType match {
//! case ADD => Add
//! case SUB => Sub
//! }
//! ctx.result = op(ctx.l.result, ctx.r.result)
| l=expr op=(NEQ|EQ|LT|LE|GT|GE) r=expr # RelExpr
//! import ToyLangParser.{NEQ,EQ,LT,LE,GT,GE}
//! val op = ctx.op.getType match {
//! case NEQ => Neq
//! case EQ => Eq
//! case LT => Lt
//! case GT => Gt
//! case LE => Le
//! case GE => Ge
//! }
//! ctx.result = op(ctx.l.result, ctx.r.result)
| op=NOT e=expr # NotExpr
//! ctx.result = Not(ctx.e.result)
|<assoc=left> l=expr op=AND r=expr # AndExpr
//! ctx.result = And(ctx.l.result, ctx.r.result)
|<assoc=left> l=expr op=OR r=expr # OrExpr
//! ctx.result = Or(ctx.l.result, ctx.r.result)
|<assoc=left> l=expr op=IMPLIES r=expr # ImpliesExpr
//! ctx.result = Implies(ctx.l.result, ctx.r.result)
| IF c=expr THEN t=expr ei+=elsif* ELSE e=expr # IteExpr
//! val elsifList = ctx.ei.view map { _.result }
//! ctx.result = Ite(ctx.c.result,
//! ctx.t.result,
//! elsifList.toList,
//! ctx.e.result)
;
elsif
locals [Elsif result]
: op=ELSIF c=expr THEN t=expr # ElsifRule
//! ctx.result = Elsif(ctx.c.result, ctx.t.result)
;
ident
locals [Ident result]
: id=IDENT # IdentRule
//! ctx.result = Ident(ctx.id.getText)
;
intNum
locals [IntNum result]
: num=INT_NUM # IntNumRule
//! ctx.result = IntNum(ctx.num.getText)
;
boolNum
locals [BoolNum result]
: num=(TRUE | FALSE) # BoolNumRule
//! ctx.result = BoolNum(ctx.num.getText)
;
COMMENT: (EOL | MLC) -> skip ;
fragment MLC: '/*' ( COMMENT | . )*? '*/' ;
fragment EOL: '//' .*? '\n' ;
LT: '<' ;
LE: '<=' ;
GT: '>' ;
GE: '>=' ;
EQ: '=' ;
NEQ: '!=' ;
ADD: '+';
AND: 'and';
DEFINE: ':=';
CARRET: '^';
ELSE: 'else';
ELSIF: 'elsif';
FALSE: 'false';
IF: 'if';
IMPLIES: 'implies';
KW_BOOL: 'bool';
KW_INT: 'int';
NOT: 'not';
OR: 'or';
SLASH: '*';
STAR: '*';
SUB: '-';
THEN: 'then';
TRUE: 'true';
INT_NUM :'0' |[1-9][0-9]* ;
IDENT:[_a-zA-Z][_a-zA-Z0-9]* ;
WS: [ \t\f\r\n]+ -> skip;
提取的侦听器如下所示:
// !!! DO NOT EDIT!!!
// Code generated from grammar ToyLang by antlr4scala
//
// scala listener header
package toylang.parser.antlr
import toylang.ast._
import scala.collection.JavaConversions._
class Listener extends ToyLangBaseListener {
// scala listener members
// stores the result of a successfull parse
var result: Option[List[Stmt]] = None
override def enterDefStmtRule( ctx: ToyLangParser.DefStmtRuleContext ): Unit = {
// entry action for alternative
println("About to parse a statement!")
}
override def exitProgramRule( ctx: ToyLangParser.ProgramRuleContext ): Unit = {
// exitAction for alternative
ctx.result = (ctx.sl.view map { _.result }).toList
result = Some(ctx.result)
}
override def exitIntType( ctx: ToyLangParser.IntTypeContext ): Unit = {
ctx.result = IntType
}
override def exitBoolType( ctx: ToyLangParser.BoolTypeContext ): Unit = {
ctx.result = BoolType
}
override def exitDefStmtRule( ctx: ToyLangParser.DefStmtRuleContext ): Unit = {
// exit action for alternative
val d = ctx.d match {
case null => None
case e@_ => Some(e.result)
}
ctx.result = DefStmt(ctx.id.result, ctx.t.result, d)
}
override def exitDefRule( ctx: ToyLangParser.DefRuleContext ): Unit = {
ctx.result = ctx.e.result
}
override def exitBoolNumExpr( ctx: ToyLangParser.BoolNumExprContext ): Unit = {
ctx.result = ctx.e.result
}
override def exitIntNumxpr( ctx: ToyLangParser.IntNumxprContext ): Unit = {
ctx.result = ctx.e.result
}
override def exitIdentExpr( ctx: ToyLangParser.IdentExprContext ): Unit = {
ctx.result = ctx.e.result
}
override def exitParenExpr( ctx: ToyLangParser.ParenExprContext ): Unit = {
ctx.result = ctx.e.result
}
override def exitUnopArithExpr( ctx: ToyLangParser.UnopArithExprContext ): Unit = {
import ToyLangParser.{ADD, SUB}
val op = ctx.op.getType match {
case ADD => Plus
case SUB => Minus
}
ctx.result = op(ctx.e.result)
}
override def exitPowerExpr( ctx: ToyLangParser.PowerExprContext ): Unit = {
ctx.result = Pow(ctx.l.result, ctx.r.result)
}
override def exitMulDivExpr( ctx: ToyLangParser.MulDivExprContext ): Unit = {
import ToyLangParser.{STAR, SLASH}
val op = ctx.op.getType match {
case STAR => Mul
case SLASH => Div
}
ctx.result = op(ctx.l.result, ctx.r.result)
}
override def exitAddSubExpr( ctx: ToyLangParser.AddSubExprContext ): Unit = {
import ToyLangParser.{ADD, SUB}
val op = ctx.op.getType match {
case ADD => Add
case SUB => Sub
}
ctx.result = op(ctx.l.result, ctx.r.result)
}
override def exitRelExpr( ctx: ToyLangParser.RelExprContext ): Unit = {
import ToyLangParser.{NEQ,EQ,LT,LE,GT,GE}
val op = ctx.op.getType match {
case NEQ => Neq
case EQ => Eq
case LT => Lt
case GT => Gt
case LE => Le
case GE => Ge
}
ctx.result = op(ctx.l.result, ctx.r.result)
}
override def exitNotExpr( ctx: ToyLangParser.NotExprContext ): Unit = {
ctx.result = Not(ctx.e.result)
}
override def exitAndExpr( ctx: ToyLangParser.AndExprContext ): Unit = {
ctx.result = And(ctx.l.result, ctx.r.result)
}
override def exitOrExpr( ctx: ToyLangParser.OrExprContext ): Unit = {
ctx.result = Or(ctx.l.result, ctx.r.result)
}
override def exitImpliesExpr( ctx: ToyLangParser.ImpliesExprContext ): Unit = {
ctx.result = Implies(ctx.l.result, ctx.r.result)
}
override def exitIteExpr( ctx: ToyLangParser.IteExprContext ): Unit = {
val elsifList = ctx.ei.view map { _.result }
ctx.result = Ite(ctx.c.result,
ctx.t.result,
elsifList.toList,
ctx.e.result)
}
override def exitElsifRule( ctx: ToyLangParser.ElsifRuleContext ): Unit = {
ctx.result = Elsif(ctx.c.result, ctx.t.result)
}
override def exitIdentRule( ctx: ToyLangParser.IdentRuleContext ): Unit = {
ctx.result = Ident(ctx.id.getText)
}
override def exitIntNumRule( ctx: ToyLangParser.IntNumRuleContext ): Unit = {
ctx.result = IntNum(ctx.num.getText)
}
override def exitBoolNumRule( ctx: ToyLangParser.BoolNumRuleContext ): Unit = {
ctx.result = BoolNum(ctx.num.getText)
}
}
原始的ANTLR 4.4仍可用于从扩展的g4文件中生成java词法分析器和解析器,生成的侦听器可以从scala中附加到java解析器。
/雷米
答案 2 :(得分:0)
您可以使用parser.program
调用的返回值将解析器结果转换为任何数据结构。我使用这种方法,发现它比访问者或听众简单得多,因为这是我实际期望解析器结果的地方。