Грамматика ANTLR4 с токенами UTF8 работает с анализатором Java и завершается неудачно с анализатором JS - PullRequest
0 голосов
/ 02 марта 2019

Я столкнулся с проблемой с моим парсером javascript.Мой парсер, сгенерированный на Java из следующей грамматики, хорошо работает с UTF-8.Вот моя следующая грамматика:

LabeledWims.g4

grammar LabeledWims;


NUM_INT             : [0-9]+;
NUM_REAL            : [0-9]+(('.' [0-9] + (EXPONENT)?)? | EXPONENT);
fragment EXPONENT   : ('e') ('+' | '-')? [0-9] +;

PLUS                : '+';
MINUS               : '-';
STAR                : '*';
SLASH               : '/';
POWER               : '^';
DOT                 : '.';
OB                  :  '{';
CB                  :  '}';
OP                  :  '(';
CP                  :  ')';

YES                 : 'yes';
NO                  : 'no';
DOTS                : '..';
EQUAL               : '=';
BSLASH              : '\\';

CRLF                : '\r'? '\n' | '\r';
WS                  :  (' ' | '\t' | '\r' | '\n') -> skip;
//NEWLINE               : '\n';
/*==============================================================*/              
/*======================== Keywords ============================*/
/*==============================================================*/  

RANDINT : 'randint';

KEYWORD
                    : RANDINT 
                    | 'shuffle'
                    | 'rows'
                    ;           // TO BE COMPLETED...

TYPE                : 'type';   //TYPE OF ANSWER DECLARATION
ANSWERTYPE
                    : 'numeric' | 'numexp'  | 'units' | 'range'| 'vector' | 'matrix'    //NUMERICAL VALUES
                    | 'correspond'                                                      //ASSOCIATION OF OBJECTS
                    | 'case' | 'nocase' | 'atext'                                       //WORD
                    | 'menu' | 'radio' | 'click' | 'checkbox' | 'flashcard' | 'mark'    //MULTIPLE CHOICE 1
                    | 'dragfill' | 'clickfill'                                          //MULTIPLE CHOICE 1
                    | 'function' | 'algexp' | 'litexp'                                  //MATH EXPRESSION                                                               // MATH FORMULA
                    ;


ID                  : [a-zA-Z] ([a-zA-Z] | [0-9] | '-' | '_' )*;


// Doc https://github.com/antlr/antlr4/blob/master/doc/lexer-rules.md#lexer-rule-elements
// INCLUDE THESE TOKENS makes unicode char include in string rule
EMOJI : [\p{Emoji}] ;
JAPANESE : [\p{Script=Hiragana}\p{Script=Katakana}\p{Script=Han}] ;
NOT_CYRILLIC : [\P{Script=Cyrillic}] ;

/*==============================================================*/
/*=================== WIMS Commands ============================*/
/*==============================================================*/
TITLE               : BSLASH 'title';
LANGUAGE            : BSLASH 'language';
AUTHOR              : BSLASH 'author';
EMAIL               : BSLASH 'email';
COMPUTEANSWER       : BSLASH 'computeanswer';
PRECISION           : BSLASH 'precision';
RANGE               : BSLASH 'range';
STATEMENT           : BSLASH 'statement';
HINT                : BSLASH 'hint';
HELP                : BSLASH 'help';

/*=================== Assignement Commands =====================*/
INTEGER             : BSLASH 'integer';
RATIONAL            : BSLASH 'rational';
REAL                : BSLASH 'real';
COMPLEX             : BSLASH 'complex';
TEXT                : BSLASH 'text';
MATRIX              : BSLASH 'matrix';
FUNCTION            : BSLASH 'function';
//ASSIGNEMENT         : INTEGER | RATIONAL | REAL | COMPLEX | TEXT | MATRIX | FUNCTION;
/*=================== Answer Commands ==========================*/
ANSWER              : BSLASH 'answer';

CONDITION           : BSLASH 'condition';
FEEDBACK            : BSLASH 'feedback';
SOLUTION            : BSLASH 'solution';


/*===========After all keywords, let s authorize the rest in unicode ========*/

sentence 
    : (string | callvariable | KEYWORD OP )+?
    ;

//string : (STRING)+;

string
 : (~(BSLASH| CB))+ ; 


/*==============================================================*/              
/*==================== Variable Assignements ===================*/
/*==============================================================*/      

integer
    : INTEGER OB assignement CB #printInt
    ;
rational
    : RATIONAL OB assignement CB
    ;
real
    : REAL OB assignement CB
    ;
complex
    : COMPLEX OB assignement CB
    ;
text
    : TEXT OB assignement CB
    ;
matrix
    : MATRIX OB assignement CB
    ;
founction
    : FUNCTION OB assignement CB
    ;

assignement
    : ID EQUAL expression                               #assign
    ;

/*==============================================================*/                  
/*====================== EXPRESSIONS ===========================*/
/*==============================================================*/                  

expression
    : expression op=(PLUS | MINUS) expression           #addSub
    | expression op=(STAR | SLASH) expression           #mulDiv
    | expression POWER expression                       #power //operator is right associative normally add <assoc=right> but generate warning
    | (PLUS | MINUS) expression                         #pluMin
    | OP expression CP                                  #parens
    | RANDINT OP expression DOTS expression CP          #keyRandint
    | callvariable                                      #id
    | NUM_INT                                           #numInt
    | NUM_REAL                                          #numReal
    ;   
callvariable
    : BSLASH ID
    ;


/*==============================================================*/                  
/*=================== WIMS EXERCICE ============================*/
/*==============================================================*/                  
//PRE EXERCISE PART
title       
    : TITLE OB string CB
    ;
language    
    : LANGUAGE OB string CB
    ;
author
    : AUTHOR OB string CB
    ;   
email
    : EMAIL OB string CB
    ;   
computeanswer
    : COMPUTEANSWER OB ( YES| NO) CB
    ;
precision
    : PRECISION OB NUM_INT CB
    ;
rangedeclaration
    : RANGE OB expression DOTS expression CB
    ;

//DURING EXERCISE PART
statement
    : STATEMENT OB sentence CB #statementExercise
    ;
hint
    : HINT OB sentence CB
    ;
help
    : HELP OB sentence CB
    ;

//POST EXERCISE PART
answer
    : ANSWER OB sentence CB
    OB callvariable CB
    answertype
    ;
answertype
    : OB TYPE EQUAL ANSWERTYPE CB
    ;
condition
    : OB sentence CB
    ;
feedback
    : FEEDBACK OB sentence CB
    ;
solution
    : SOLUTION OB sentence CB
    ;

wims :  
    title                       
    ('\n')+language                     
    ('\n')+author                       
    ('\n')+email                        
    ('\n')+computeanswer                        
    ('\n')+precision                                    
    (('\n')+rangedeclaration)*                      
    (('\n')+integer)*                           
    ('\n')+statement                    
    ('\n')+answer                       
    ;

Пример простого исходного кода, который я хочу проанализировать:

\title{Un pré bis}
\language{fr}
\author{Mr. Toto}
\email{toto@univ.com}
\computeanswer{no}
\precision{10000}
\integer{L = 10*randint(1..10)} 
\integer{l = 10*randint(1..10) }
\integer{per = 2*(\L+\l)}
\statement{Donner le périmètre d'un pré rectangulaire de longueur \L m et de largeur \l m.}
\answer{périmetre (en m)}{\per}{type=numeric}

Я сгенерировал мой анализатор Java с помощью:

antlr4 -no-listener -visitor LabeledWims.g4

Затем я вызываю в основном классе Java анализатор с:

  CharStream input = CharStreams.fromFileName(inputFile);
    LabeledWimsLexer lexer = new LabeledWimsLexer(input);
    CommonTokenStream tokens = new CommonTokenStream(lexer);
    LabeledWimsParser parser = new LabeledWimsParser(tokens);
    ParseTree tree = parser.wims(); // begin parsing at init rule        
    System.out.println(tree.toStringTree(parser)+"\n"); // print LISP-style tree
    EvalVisitor eval = new EvalVisitor();
    eval.visit(tree);

Как видите, я использую класс CharStream, чтобы разрешить символы UTF-8 в моем исходном коде. Он генерирует следующее правильно сформированное дерево LISP:

(wims (title \title { (string Un pr é bis) }) \n (language...

(каждыйUTF-8 char генерирует токен, но на данный момент это не имеет значения)

Тогда я бы хотел сделать то же самое в Javascript.Я сгенерировал Javascript Parser благодаря graddle с аргументами '-Dlanguage = JavaScript', 'LabeledWims.g4', '- o', 'static / generate-parser'

и вызвал анализатор в сценарии JSс помощью:

var lexer = new TodoLexer.LabeledWimsLexer(chars);
var tokens  = new antlr4.CommonTokenStream(lexer);
console.log("Parsed: "+ tokens);
var parser = new TodoParser.LabeledWimsParser(tokens);
parser.buildParseTrees = true;
var tree = parser.wims();

var extractor = new MyWimsListener();
antlr4.tree.ParseTreeWalker.DEFAULT.walk(extractor, tree);

Но там сгенерированное дерево LISP избегает использования символа UTF-8 следующим образом:

(wims (title \title { (string Un pr bis) }) \n (language...

Как вы можете видеть, 'é' исчезает из дерева.Я пытался из браузера и текстовой области, а также скрипт node.js в терминале, результаты одинаковы.Я не могу определить источник этой проблемы.Буду благодарен за вашу помощь.

Крис

...