Я новичок в C # и ANTLR, и я не могу понять, как выполнять интерактивный построчный анализ, используя ANTLR4, точно так же, как это показано в действиях / инструментах / calc Книги 4 ANTLR.Пример java в главе 10, который использует класс BufferedReader (насколько я могу судить, у .NET / C # нет эквивалента), где каждая строка ввода анализируется сразу, а не все в конце.Ясно, что я мог бы просто создать новые экземпляры входного потока, лексера, потока токенов и анализатора для каждой строки ввода, но это, похоже, не самое эффективное решение.Как правильно C # способ сделать это?
Есть ли где-нибудь репозиторий, содержащий переводы C # примеров программ?Кроме того, есть ли документ, который описывает различия между временем выполнения Java и временем выполнения C #?(например, в примере calc.java у автора есть такая строка:
ExprParser parser = new ExprParser(null); // share single parser instance
, которая не работает со средой выполнения C #)
Вот код calc.java для справки:
/***
* Excerpted from "The Definitive ANTLR 4 Reference",
* published by The Pragmatic Bookshelf.
* Copyrights apply to this code. It may not be used to create training material,
* courses, books, articles, and the like. Contact us if you are in doubt.
* We make no guarantees that this code is fit for any purpose.
* Visit http://www.pragmaticprogrammer.com/titles/tpantlr2 for more book information.
***/
package tools;
import org.antlr.v4.runtime.ANTLRInputStream;
import org.antlr.v4.runtime.CommonTokenStream;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
public class Calc {
public static void main(String[] args) throws Exception {
String inputFile = null;
if ( args.length>0 ) inputFile = args[0];
InputStream is = System.in;
if ( inputFile!=null ) {
is = new FileInputStream(inputFile);
}
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String expr = br.readLine(); // get first expression
int line = 1; // track input expr line numbers
ExprParser parser = new ExprParser(null); // share single parser instance
parser.setBuildParseTree(false); // don't need trees
while ( expr!=null ) { // while we have more expressions
// create new lexer and token stream for each line (expression)
ANTLRInputStream input = new ANTLRInputStream(expr+"\n");
ExprLexer lexer = new ExprLexer(input);
lexer.setLine(line); // notify lexer of input position
lexer.setCharPositionInLine(0);
CommonTokenStream tokens = new CommonTokenStream(lexer);
parser.setInputStream(tokens); // notify parser of new token stream
parser.stat(); // start the parser
expr = br.readLine(); // see if there's another line
line++;
}
}
}
Вот грамматика:
/** Grammar from tour chapter augmented with actions */
grammar Expr;
options
{
language = CSharp; // The semantic actions are written in C#, so this grammar can only be used with the C# code generator
}
@parser::members
{
/** "memory" for our calculator; variable/value pairs go here */
Dictionary <string, int> memory = new Dictionary <string, int> ();
int eval (int left, int op, int right)
{
switch (op)
{
case MUL : return left * right;
case DIV : return left / right;
case ADD : return left + right;
case SUB : return left - right;
}
return 0;
} // End eval
}
stat: e NEWLINE {Console.WriteLine ($e.v);}
| ID '=' e NEWLINE {memory.Add ($ID.text, $e.v);}
| NEWLINE
;
e returns [int v]
: a=e op=('*'|'/') b=e {$v = eval ($a.v, $op.type, $b.v);}
| a=e op=('+'|'-') b=e {$v = eval ($a.v, $op.type, $b.v);}
| INT {$v = $INT.int;}
| ID
{
string id = $ID.text;
$v = memory.ContainsKey (id) ? memory [id] : 0;
}
| '(' e ')' {$v = $e.v;}
;
MUL : '*' ;
DIV : '/' ;
ADD : '+' ;
SUB : '-' ;
ID : [a-zA-Z]+ ; // match identifiers
INT : [0-9]+ ; // match integers
NEWLINE:'\r'? '\n' ; // return newlines to parser (is end-statement signal)
WS : [ \t]+ -> skip ; // toss out whitespace