首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >PegJS数学解析

PegJS数学解析
EN

Stack Overflow用户
提问于 2019-03-01 21:00:40
回答 1查看 106关注 0票数 0

目前,我的语法支持基本的变量赋值,我将在这个例子中使用它,但我在数学解析方面遇到了一些问题。当尝试使用以下命令时,它会正确返回:

代码语言:javascript
复制
test = 10^2

例如,但它返回:

代码语言:javascript
复制
Line 1, column 8: Expected "(", "/*", "false", "null", "true", identifier, number, string, or whitespace but "1" found.

当尝试使用以下命令时:

代码语言:javascript
复制
test = 10MOD2

奇怪的是,它在尝试使用时似乎工作得很好:

代码语言:javascript
复制
test = 10 MOD2

下面是我的语法:

代码语言:javascript
复制
Start
  = __ program:Program __ { return program; }

// ----- A.1 Lexical Grammar -----

SourceCharacter
  = .

WhiteSpace "whitespace"
  = "\t"
  / "\v"
  / "\f"
  / " "
  / "\u00A0"
  / "\uFEFF"

LineTerminator
  = [\n\r\u2028\u2029]

LineTerminatorSequence "end of line"
  = "\n"
  / "\r\n"
  / "\r"
  / "\u2028"
  / "\u2029"

Comment "comment"
  = MultiLineComment
  / SingleLineComment

MultiLineComment
  = "/*" (!"*/" SourceCharacter)* "*/"

MultiLineCommentNoLineTerminator
  = "/*" (!("*/" / LineTerminator) SourceCharacter)* "*/"

SingleLineComment
  = "//" (!LineTerminator SourceCharacter)*

Identifier
  = !ReservedWord name:IdentifierName { return name; }

IdentifierName "identifier"
  = head:IdentifierStart tail:IdentifierPart* {
      return {
        type: "Identifier",
        name: head + tail.join("")
      };
    }

IdentifierStart
  = UnicodeLetter

IdentifierPart
  = IdentifierStart
  / UnicodeDigit
  / "\u200C"
  / "\u200D"

UnicodeLetter
  = [a-zA-Z]

UnicodeDigit
  = [0-9]

ReservedWord
  = Keyword
  / FutureReservedWord
  / NullLiteral
  / BooleanLiteral

Keyword
  = BreakToken
  / CaseToken
  / CatchToken
  / ContinueToken
  / DebuggerToken
  / DefaultToken
  / DeleteToken
  / DoToken
  / ElseToken
  / FinallyToken
  / ForToken
  / FunctionToken
  / IfToken
  / InstanceofToken
  / InToken
  / NewToken
  / ReturnToken
  / SwitchToken
  / ThisToken
  / ThrowToken
  / TryToken
  / TypeofToken
  / VarToken
  / VoidToken
  / WhileToken
  / WithToken
  / GlobalToken
  / ModulusToken
  / QuotientToken

FutureReservedWord
  = ClassToken
  / ConstToken
  / EnumToken
  / ExportToken
  / ExtendsToken
  / ImportToken
  / SuperToken

Literal
  = NullLiteral
  / BooleanLiteral
  / NumericLiteral
  / StringLiteral

NullLiteral
  = NullToken { return { type: "Literal", value: null }; }

BooleanLiteral
  = TrueToken  { return { type: "Literal", value: true  }; }
  / FalseToken { return { type: "Literal", value: false }; }

// The "!(IdentifierStart / DecimalDigit)" predicate is not part of the official
// grammar, it comes from text in section 7.8.3.
NumericLiteral "number"
  = literal:DecimalLiteral !(IdentifierStart / DecimalDigit) {
      return literal;
    }

DecimalLiteral
  = DecimalIntegerLiteral "." DecimalDigit* {
      return { type: "Literal", value: parseFloat(text()) };
    }
  / "." DecimalDigit+ {
      return { type: "Literal", value: parseFloat(text()) };
    }
  / DecimalIntegerLiteral {
      return { type: "Literal", value: parseFloat(text()) };
    }

DecimalIntegerLiteral
  = "0"
  / NonZeroDigit DecimalDigit*

DecimalDigit
  = [0-9]

NonZeroDigit
  = [1-9]

ExponentPart
  = ExponentIndicator SignedInteger

ExponentIndicator
  = "e"i

SignedInteger
  = [+-]? DecimalDigit+

StringLiteral "string"
  = '"' chars:DoubleStringCharacter* '"' {
      return { type: "Literal", value: chars.join("") };
    }
  / "'" chars:SingleStringCharacter* "'" {
      return { type: "Literal", value: chars.join("") };
    }

DoubleStringCharacter
  = !('"' / "\\" / LineTerminator) SourceCharacter { return text(); }
  / "\\" sequence:EscapeSequence { return sequence; }
  / LineContinuation

SingleStringCharacter
  = !("'" / "\\" / LineTerminator) SourceCharacter { return text(); }
  / "\\" sequence:EscapeSequence { return sequence; }
  / LineContinuation

LineContinuation
  = "\\" LineTerminatorSequence { return ""; }

EscapeSequence
  = CharacterEscapeSequence
  / "0" !DecimalDigit { return "\0"; }

CharacterEscapeSequence
  = SingleEscapeCharacter
  / NonEscapeCharacter

SingleEscapeCharacter
  = "'"
  / '"'
  / "\\"
  / "b"  { return "\b"; }
  / "f"  { return "\f"; }
  / "n"  { return "\n"; }
  / "r"  { return "\r"; }
  / "t"  { return "\t"; }
  / "v"  { return "\v"; }

NonEscapeCharacter
  = !(EscapeCharacter / LineTerminator) SourceCharacter { return text(); }

EscapeCharacter
  = SingleEscapeCharacter
  / DecimalDigit
  / "x"
  / "u"

BreakToken      = "break"      !IdentifierPart
CaseToken       = "case"       !IdentifierPart
CatchToken      = "catch"      !IdentifierPart
ClassToken      = "class"      !IdentifierPart
ConstToken      = "const"      !IdentifierPart
ContinueToken   = "continue"   !IdentifierPart
DebuggerToken   = "debugger"   !IdentifierPart
DefaultToken    = "default"    !IdentifierPart
DeleteToken     = "delete"     !IdentifierPart
DoToken         = "do"         !IdentifierPart
ElseToken       = "else"       !IdentifierPart
EnumToken       = "enum"       !IdentifierPart
ExportToken     = "export"     !IdentifierPart
ExtendsToken    = "extends"    !IdentifierPart
FalseToken      = "false"      !IdentifierPart
FinallyToken    = "finally"    !IdentifierPart
ForToken        = "for"        !IdentifierPart
FunctionToken   = "function"   !IdentifierPart
GetToken        = "get"        !IdentifierPart
IfToken         = "if"         !IdentifierPart
ImportToken     = "import"     !IdentifierPart
InstanceofToken = "instanceof" !IdentifierPart
InToken         = "in"         !IdentifierPart
NewToken        = "new"        !IdentifierPart
NullToken       = "null"       !IdentifierPart
ReturnToken     = "return"     !IdentifierPart
SetToken        = "set"        !IdentifierPart
SuperToken      = "super"      !IdentifierPart
SwitchToken     = "switch"     !IdentifierPart
ThisToken       = "this"       !IdentifierPart
ThrowToken      = "throw"      !IdentifierPart
TrueToken       = "true"       !IdentifierPart
TryToken        = "try"        !IdentifierPart
TypeofToken     = "typeof"     !IdentifierPart
VarToken        = "var"        !IdentifierPart
VoidToken       = "void"       !IdentifierPart
WhileToken      = "while"      !IdentifierPart
WithToken       = "with"       !IdentifierPart
GlobalToken     = "global"     !IdentifierPart
ModulusToken    = "MOD"        !IdentifierPart
QuotientToken   = "DIV"        !IdentifierPart

// Skipped

___
  = (WhiteSpace / /*LineTerminatorSequence / Comment*/ MultiLineCommentNoLineTerminator)+
__
  = (WhiteSpace / LineTerminatorSequence / Comment)*

_
  = (WhiteSpace / MultiLineCommentNoLineTerminator)*

Program
  = __ body:StatementList __ {
  return {
    type: "Program",
    body: body
  }
  }

StatementList
  = (Statement)*

Statement
  = __ body:(VariableAssignment / GlobalAssignment) __
  {
  return body
  }

MathematicalExpression = additive

additive = left:multiplicative _ atag:("+" / "-") _ right:additive { return {type: "MathematicalExpression", operator: atag, left:left, right:right}; } / multiplicative 

multiplicative = left:exponential _ atag:("*" / "/" / "MOD" / "DIV") _ right:multiplicative { return {type: "MathematicalExpression", operator: atag, left:left, right:right}; } / exponential

exponential = left:primary _ atag:("^") _ right:exponential { return {type: "MathematicalExpression", operator: atag, left:left, right:right}; } / primary

primary = (DirectValueIntegerNoEq) / "(" additive:additive ")" { return additive; }


DirectValue
 = MathematicalExpression
 / Literal
 / Identifier

DirectValueInteger
 = MathematicalExpression
 / NumericLiteral
 / Identifier

DirectValueIntegerNoEq
 = NumericLiteral
 / Identifier

VariableAssignment
  = left:Identifier _ "=" _ right:DirectValue
  {
  return {
  type: "VariableAssignment",
  left: left,
  right: right
  }
  }

GlobalAssignment
  = GlobalToken ___ left:Identifier _ "=" _ right:DirectValue
  {
  return {
  type: "GlobalAssignment",
  left: left,
  right: right
  }
  }
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-03-29 07:30:21

您需要在NumericLiteral中删除!IdentifierStart。因为MOD可能是一个IdentifierStart。您的第二个示例(test = 10 MOD2)之所以有效,是因为MOD2被视为标识符,而不是MOD操作。

例如,更改以下内容:

代码语言:javascript
复制
// The "!(IdentifierStart / DecimalDigit)" predicate is not part of the official
// grammar, it comes from text in section 7.8.3.
NumericLiteral "number"
  = literal:DecimalLiteral !(IdentifierStart / DecimalDigit) {
      return literal;
    }

要这样做:

代码语言:javascript
复制
// The "!(IdentifierStart / DecimalDigit)" predicate is not part of the official
// grammar, it comes from text in section 7.8.3.
NumericLiteral "number"
  = literal:DecimalLiteral !DecimalDigit {
      return literal;
    }

输出:

代码语言:javascript
复制
{
   "type": "Program",
   "body": [
      {
         "type": "VariableAssignment",
         "left": {
            "type": "Identifier",
            "name": "test"
         },
         "right": {
            "type": "MathematicalExpression",
            "operator": "MOD",
            "left": {
               "type": "Literal",
               "value": 10
            },
            "right": {
               "type": "Literal",
               "value": 2
            }
         }
      }
   ]
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54945213

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档