计算器

java 是默认的,指定语言为 C#.

options {
 language = "CSharp";
}

语法分析器,派生自 Parser。

以下依次为

选项

语法定义

class CalcParser extends Parser;
options {
 buildAST = true; // uses CommonAST by default
}

expr
 : mexpr (PLUS^ mexpr)* SEMI!
 ;

mexpr
 : atom (STAR^ atom)*
 ;

atom: INT
 ;

词法分析器,派生自 Lexer。

class CalcLexer extends Lexer;

WS : (' '
 | '/t'
 | '/n'
 | '/r')
  { _ttype = Token.SKIP; }
 ;

LPAREN: '('
 ;

RPAREN: ')'
 ;

STAR: '*'
 ;

PLUS: '+'
 ;

SEMI: ';'
 ;

protected
DIGIT
 : '0'..'9'
 ;

INT : (DIGIT)+
 ;

解释器。

定义对 expr 的解释方法。

class CalcTreeWalker extends TreeParser;

expr returns [float r]
{
 float a,b;
 r=0;
}
 : #(PLUS a=expr b=expr) {r = a+b;}
 | #(STAR a=expr b=expr) {r = a*b;}
 | i:INT   {r = Convert.ToSingle(i.getText());}
 ;

过程为先由词法分析器识别出单词/符号,交由语法分析程序识别出其语境的含义。

细看词法分析器的写法:

class CalcLexer extends Lexer;

// 遇到 tab、换行,识别为 WS

// 对 WS,语法分析器不去识别,注明为可跳过去单词/字符

WS : (' '
 | '/t'
 | '/n'
 | '/r')
  { _ttype = Token.SKIP; }
 ;

// 括号

LPAREN: '('
 ;

RPAREN: ')'
 ;

// 星星

STAR: '*'
 ;

// 加号

PLUS: '+'
 ;

// ....

SEMI: ';'
 ;

// 这些可以继承

protected

// 数字
DIGIT
 : '0'..'9'
 ;

// 整数

// 整数的定义在词法分析器中。

// 如果要做 C# 文法,识别 Console.WriteLine,xxx.yyy() xxx 该在何处定义呢

INT : (DIGIT)+
 ;

语法分析器:

class CalcParser extends Parser;

// 指定生成抽象语法树
options {
 buildAST = true; // uses CommonAST by default
}

// 表达式定义

// 算子,整数

atom: INT
 ;

// 乘法定义(不支持除法)

// 乘法是算子乘算子乘算子乘算子乘算子。。。。

// 或者直接就是算子。以 星星 为树把。

mexpr
 : atom (STAR^ atom)*
 ;

// 表达式为乘法加乘法加乘法加乘法加乘法加乘法加乘法。。

// 用分号结束

// 以加号作为树把

expr
 : mexpr (PLUS^ mexpr)* SEMI!
 ;

如何解释分析出来的树

class CalcTreeWalker extends TreeParser;

expr returns [float r]
{
 float a,b;
 r=0;
}
 : #(PLUS a=expr b=expr) {r = a+b;}
 | #(STAR a=expr b=expr) {r = a*b;}
 | i:INT   {r = Convert.ToSingle(i.getText());}
 ;

这个家伙变成 public float  expr(AST ) 的方法,处理传入的抽象语法树。

它返回 float r。

具体的代码含义为:

如果传入 AST 把类型为加,亦即由 PLUS^ 建立的树把,把树分成 a b 两枝,分别递归求值。返回二者之和。

如果 AST 把类型为乘。分成两支,相乘。

最后,如果传入的是 int 单词,转为 int 类型数字。

ANTLR 将该文件变成 CalcLexer.cs,CalcParser.cs,CalcParserTokenTypes.cs 和 CalcTreeWalker.cs

在如下 C# 中使用它:

class Calc
{
 public static void Main(string[] args)
 {
  try
  {
   CalcLexer lexer = new CalcLexer(new CharBuffer(Console.In));
   lexer.setFilename("<stdin>");
   CalcParser parser = new CalcParser(lexer);
   parser.setFilename("<stdin>");

   // 分析传入的文本
   parser.expr();

  // 取 AST 根把
   CommonAST t = (CommonAST)parser.getAST();
   
   // Print the resulting tree out in LISP notation
   Console.Out.WriteLine(t.ToStringTree());

   // 分析器登场
   CalcTreeWalker walker = new CalcTreeWalker();
   
   // 使用分析器的方法分析根把

   float r = walker.expr(t);
   Console.Out.WriteLine("value is "+r); // 出结果
  }
  catch(TokenStreamException e)
  {
   Console.Error.WriteLine("exception: "+e);
  }
  catch(RecognitionException e)
  {
   Console.Error.WriteLine("exception: "+e);
  }
 } 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值