【问题标题】:Dart and Antlr4 on Web - Mismatched InputWeb 上的 Dart 和 Antlr4 - 输入不匹配
【发布时间】:2022-10-18 23:07:14
【问题描述】:

哇,这是一个措辞可怕的查询,让我再试一次。

我仍在学习 antlr 并尝试理解语法。我正在使用语法(不是我写的 - 所以我尽量不要调整太多,因为它是许多团体使用的标准,found here)。

我在 Flutter 应用程序中使用它。当我在 Linux 或 Android 上运行它时,它运行没有问题。当我尝试在没有网络的情况下运行它时,我立即遇到了问题。我正在使用的完整语法如下。

grammar FhirPath;

// Grammar rules [FHIRPath](http://hl7.org/fhirpath/N1) Normative Release

//prog: line (line)*; line: ID ( '(' expr ')') ':' expr '\r'? '\n';
entireExpression: expression EOF;

expression:
    term                                                # termExpression
    | expression '.' invocation                         # invocationExpression
    | expression '[' expression ']'                     # indexerExpression
    | ('+' | '-') expression                            # polarityExpression
    | expression ('*' | '/' | 'div' | 'mod') expression # multiplicativeExpression
    | expression ('+' | '-' | '&') expression           # additiveExpression
    | expression '|' expression                         # unionExpression
    | expression ('<=' | '<' | '>' | '>=') expression   # inequalityExpression
    | expression ('is' | 'as') typeSpecifier            # typeExpression
    | expression ('=' | '~' | '!=' | '!~') expression   # equalityExpression
    | expression ('in' | 'contains') expression         # membershipExpression
    | expression 'and' expression                       # andExpression
    | expression ('or' | 'xor') expression              # orExpression
    | expression 'implies' expression                   # impliesExpression;
//| (IDENTIFIER)? '=>' expression                             #lambdaExpression

term:
    invocation              # invocationTerm
    | literal               # literalTerm
    | externalConstant      # externalConstantTerm
    | '(' expression ')'    # parenthesizedTerm;

literal:
    '{' '}'                 # nullLiteral
    | ('true' | 'false')    # booleanLiteral
    | STRING                # stringLiteral
    | NUMBER                # numberLiteral
    | DATE                  # dateLiteral
    | DATETIME              # dateTimeLiteral
    | TIME                  # timeLiteral
    | quantity              # quantityLiteral;

externalConstant: '%' ( identifier | STRING);

invocation: // Terms that can be used after the function/member invocation '.'
    identifier  # memberInvocation
    | function  # functionInvocation
    | '$this'   # thisInvocation
    | '$index'  # indexInvocation
    | '$total'  # totalInvocation;

function: identifier '(' paramList? ')';

paramList: expression (',' expression)*;

quantity: NUMBER unit?;

unit:
    pluralDateTimePrecision
    | dateTimePrecision
    | STRING; // UCUM syntax for units of measure

pluralDateTimePrecision:
    'years'
    | 'months'
    | 'weeks'
    | 'days'
    | 'hours'
    | 'minutes'
    | 'seconds'
    | 'milliseconds';

dateTimePrecision:
    'year'
    | 'month'
    | 'week'
    | 'day'
    | 'hour'
    | 'minute'
    | 'second'
    | 'millisecond';

typeSpecifier: qualifiedIdentifier;

qualifiedIdentifier: identifier ('.' identifier)*;

identifier:
    IDENTIFIER
    | DELIMITEDIDENTIFIER
    | 'as'
    | 'is'
    | 'contains'
    | 'in'
    | 'div';

/****************************************************************
 Lexical rules ***************************************************************
 */

/*
 NOTE: The goal of these rules in the grammar is to provide a date token to the parser. As such it
 is not attempting to validate that the date is a correct date, that task is for the parser or
 interpreter.
 */

DATE: '@' DATEFORMAT;

DATETIME:
    '@' DATEFORMAT 'T' (TIMEFORMAT TIMEZONEOFFSETFORMAT?)?;

TIME: '@' 'T' TIMEFORMAT;

fragment DATEFORMAT:
    [0-9][0-9][0-9][0-9] ('-' [0-9][0-9] ('-' [0-9][0-9])?)?;

fragment TIMEFORMAT:
    [0-9][0-9] (':' [0-9][0-9] (':' [0-9][0-9] ('.' [0-9]+)?)?)?;

fragment TIMEZONEOFFSETFORMAT: (
        'Z'
        | ('+' | '-') [0-9][0-9]':' [0-9][0-9]
    );

IDENTIFIER: ([A-Za-z] | '_') ([A-Za-z0-9] | '_')*;
// Added _ to support CQL (FHIR could constrain it out)

DELIMITEDIDENTIFIER: '`' (ESC | ~[\\`])* '`';

STRING: '\'' (ESC | ~['])* '\'';

// Also allows leading zeroes now (just like CQL and XSD)
NUMBER: [0-9]+ ('.' [0-9]+)?;

// Pipe whitespace to the HIDDEN channel to support retrieving source text through the parser.
WS: [ \r\n\t]+ -> channel(HIDDEN);

COMMENT: '/*' .*? '*/' -> channel(HIDDEN);

LINE_COMMENT: '//' ~[\r\n]* -> channel(HIDDEN);

fragment ESC:
    '\\' ([`'\\/fnrt] | UNICODE); // allow \`, \', \\, \/, \f, etc. and \uXXX

fragment UNICODE: 'u' HEX HEX HEX HEX;

fragment HEX: [0-9a-fA-F];

我使用以下代码生成代码:

antlr4 -Dlanguage=Dart FhirPath.g4 -visitor -no-listener

然后测试我使用以下代码:

final input = InputStream.fromString('name');
final lexer = FhirPathLexer(input);
final tokens = CommonTokenStream(lexer);
final parser = FhirPathParser(tokens);
parser.buildParseTree = true;
final tree = parser.expression();

如果我在一个简单的飞镖脚本中运行它,它运行没有问题。但是,如果我将它放在 Flutter 应用程序中(同样,仅在 Web 上,否则它似乎可以毫无问题地运行),我会收到以下错误:

line 1:0 mismatched input 'name' expecting {'as', 'in', 'is', 'contains', 'div', 'mod', IDENTIFIER, DELIMITEDIDENTIFIER}

我假设我对语法有一些不理解的地方,所以任何见解都会受到赞赏。

【问题讨论】:

  • 仍然有不少与此错误无关的令牌识别错误,因此我无法重现您的输出器。请尝试测试您发布的语法是否有效并产生您在问题中给出的输出。这是一种很容易去除太多东西的方法,它确实使回答问题变得更加困难)
  • 我不明白这与 Flutter 有什么关系?
  • 这与 Flutter 有关,因为我可以在 Android 或 Linux 的 Flutter 应用程序中运行它,但不能在 Web 中运行。此外,同样的语法用于 Javascript 和 Python 并且有效,所以我试图找出差异在哪里。
  • 这听起来与在您的 Web 应用程序中使用的生成解析器相比,在 Dart 脚本中使用时生成的解析器是不同的。确保您使用的是相同的生成解析器。
  • 我删除了我的答案...我误读了您的问题并将您的代码误认为是整个输入。我已经使用您提供的语法和name 输入重新运行,并获得了良好的输出。 “名称”被标记为IDENTIFIER。 (这是使用 Java 目标来测试语法。)

标签: flutter dart antlr antlr4


【解决方案1】:

我已经得出结论,这是转换为 javascript 的错误。 antlr4 版本适用于我对 Android 和 Linux 的所有测试,然后会为 web 引发一堆错误。我已经回到使用petitparser 而不是antlr4。如果其他人有任何建议,请随时离开,但现在,我将关闭它。如果你想比较两者的外观,我这里有两个版本:https://github.com/MayJuun/fhir/tree/main/fhir_path/lib

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-12-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-01
    • 1970-01-01
    • 2018-09-27
    相关资源
    最近更新 更多