|
@@ -69,10 +69,9 @@ STATEMENTS -> STATEMENT STATEMENTS | .
|
|
|
STATEMENT -> BLOCK | CHAIN eos | eos .
|
|
|
CHAIN -> COMMAND LINKS .
|
|
|
LINKS -> LINK LINKS | .
|
|
|
-LINK -> operator COMMAND .
|
|
|
-COMMAND -> DIRECT | INDIRECT | LITERAL .
|
|
|
-DIRECT -> NAME PARAMETERS .
|
|
|
-INDIRECT -> SUBSTITUTION PARAMETERS .
|
|
|
+LINK -> operator EXPRESSION .
|
|
|
+EXPRESSION -> COMMAND | SUBSTITUTION | LITERAL .
|
|
|
+COMMAND -> NAME PARAMETERS .
|
|
|
PARAMETER -> NAME | LITERAL | SUBSTITUTION | BLOCK .
|
|
|
SUBSTITUTION -> PARENTHESIS | GETTER | SETTER | LIST .
|
|
|
PARENTHESIS -> openparen CHAIN closeparen .
|
|
@@ -238,15 +237,22 @@ func AstKindForToken(token Token) AstKind {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-func (parser *Parser) ParseWordValue() *Ast {
|
|
|
- parser.LogDebug("ParseWordValue: %s\n", parser.current.String())
|
|
|
+func (parser *Parser) ParseLiteral() *Ast {
|
|
|
+ parser.LogDebug("ParseLiteral: %s\n", parser.current.String())
|
|
|
|
|
|
value := parser.Require(TokenKindInteger, TokenKindString,
|
|
|
- TokenKindBoolean, TokenKindNil, TokenKindFloat, TokenKindSymbol,
|
|
|
- TokenKindType, TokenKindWord)
|
|
|
-
|
|
|
+ TokenKindBoolean, TokenKindNil, TokenKindFloat)
|
|
|
astKind := AstKindForToken(value)
|
|
|
-
|
|
|
+
|
|
|
+ return parser.NewAst(astKind, nil, EmptyAstArray(), value)
|
|
|
+}
|
|
|
+
|
|
|
+func (parser *Parser) ParseName() *Ast {
|
|
|
+ parser.LogDebug("ParseName: %s\n", parser.current.String())
|
|
|
+
|
|
|
+ value := parser.Require(TokenKindWord, TokenKindType, TokenKindSymbol)
|
|
|
+ astKind := AstKindForToken(value)
|
|
|
+
|
|
|
return parser.NewAst(astKind, nil, EmptyAstArray(), value)
|
|
|
}
|
|
|
|
|
@@ -254,10 +260,10 @@ func (parser *Parser) ParseArgument() *Ast {
|
|
|
parser.LogDebug("ParseArgument: %s\n", parser.current.String())
|
|
|
|
|
|
switch {
|
|
|
- case parser.NextIsGet(): return parser.ParseGet()
|
|
|
- case parser.NextIsSet(): return parser.ParseSet()
|
|
|
- case parser.NextIsClosed(): return parser.ParseClosed()
|
|
|
- case parser.NextIsWordValue(): return parser.ParseWordValue()
|
|
|
+ case parser.NextIsName(): return parser.ParseName()
|
|
|
+ case parser.NextIsBlock(): return parser.ParseBlock()
|
|
|
+ case parser.NextIsSubstitution(): return parser.ParseSubstitution()
|
|
|
+ case parser.NextIsLiteral(): return parser.ParseLiteral()
|
|
|
default: parser.Panicf("error: in argument: expected $, =, }, word or value")
|
|
|
return nil
|
|
|
}
|
|
@@ -311,9 +317,9 @@ func (parser *Parser) ParseParenthesis() *Ast {
|
|
|
|
|
|
|
|
|
ast := NewAstWithToken(AstKindParenthesis, op)
|
|
|
- expr := parser.ParseExpression()
|
|
|
+ expr := parser.ParseChain()
|
|
|
if expr.IsNone() {
|
|
|
- return parser.NewAstError("expected expression")
|
|
|
+ return parser.NewAstError("expected chain")
|
|
|
}
|
|
|
if AstIsError(expr) {
|
|
|
return expr
|
|
@@ -350,24 +356,24 @@ func (parser *Parser) ParseBlock() *Ast {
|
|
|
return ast
|
|
|
}
|
|
|
|
|
|
+func (parser *Parser) RequireName() Token {
|
|
|
+ return parser.Require(TokenKindWord, TokenKindType, TokenKindSymbol)
|
|
|
+}
|
|
|
+
|
|
|
|
|
|
func (parser *Parser) ParseTarget() *Ast {
|
|
|
parser.LogDebug("ParseTarget: %s\n", parser.current.String())
|
|
|
var target *Ast
|
|
|
|
|
|
switch {
|
|
|
- case parser.NextIs(TokenKindWord, TokenKindType, TokenKindSymbol):
|
|
|
+ case parser.NextIsName():
|
|
|
|
|
|
- token := parser.Require(TokenKindWord, TokenKindType, TokenKindSymbol)
|
|
|
+ token := parser.RequireName()
|
|
|
target = NewAstWithToken(AstKindTarget, token)
|
|
|
- case parser.NextIsGet():
|
|
|
+ case parser.NextIsSubstitution():
|
|
|
|
|
|
target = NewAstWithToken(AstKindTarget, parser.current)
|
|
|
- target.AppendChild(parser.ParseGet())
|
|
|
- case parser.NextIsClosed():
|
|
|
-
|
|
|
- target = NewAstWithToken(AstKindTarget, parser.current)
|
|
|
- target.AppendChild(parser.ParseClosed())
|
|
|
+ target.AppendChild(parser.ParseSubstitution())
|
|
|
default:
|
|
|
parser.Panicf("Malformed setter.")
|
|
|
return nil
|
|
@@ -388,18 +394,13 @@ func (parser *Parser) ParseOrigin() *Ast {
|
|
|
var target *Ast
|
|
|
|
|
|
switch {
|
|
|
- case parser.NextIs(TokenKindWord, TokenKindType, TokenKindSymbol):
|
|
|
+ case parser.NextIsName():
|
|
|
|
|
|
- token := parser.Require(TokenKindWord, TokenKindType, TokenKindSymbol)
|
|
|
+ token := parser.RequireName()
|
|
|
target = NewAstWithToken(AstKindTarget, token)
|
|
|
- case parser.NextIsGet():
|
|
|
-
|
|
|
- target = NewAstWithToken(AstKindTarget, parser.current)
|
|
|
- target.AppendChild(parser.ParseGet())
|
|
|
- case parser.NextIsClosed():
|
|
|
-
|
|
|
+ case parser.NextIsSubstitution():
|
|
|
target = NewAstWithToken(AstKindTarget, parser.current)
|
|
|
- target.AppendChild(parser.ParseClosed())
|
|
|
+ target.AppendChild(parser.ParseSubstitution())
|
|
|
default:
|
|
|
parser.Panicf("Malformed getter")
|
|
|
return nil
|
|
@@ -439,14 +440,15 @@ func (parser *Parser) ParseCommand() *Ast {
|
|
|
return command
|
|
|
}
|
|
|
|
|
|
-func (parser *Parser) ParseClosed() *Ast {
|
|
|
- parser.LogDebug("ParseClosed: %s\n", parser.current.String())
|
|
|
+func (parser *Parser) ParseSubstitution() *Ast {
|
|
|
+ parser.LogDebug("ParseSubstitution: %s\n", parser.current.String())
|
|
|
switch {
|
|
|
- case parser.NextIs(TokenKindOpenBlock): return parser.ParseBlock()
|
|
|
case parser.NextIs(TokenKindOpenParen): return parser.ParseParenthesis()
|
|
|
case parser.NextIs(TokenKindOpenList): return parser.ParseList()
|
|
|
+ case parser.NextIs(TokenKindGet): return parser.ParseGet()
|
|
|
+ case parser.NextIs(TokenKindSet): return parser.ParseSet()
|
|
|
default:
|
|
|
- parser.Panicf("Syntax error in closed, expected {, (, [")
|
|
|
+ parser.Panicf("Syntax error in substitution, expected $, =, (, [")
|
|
|
return nil
|
|
|
}
|
|
|
}
|
|
@@ -457,9 +459,8 @@ func (parser *Parser) ParseExpression() *Ast {
|
|
|
|
|
|
switch {
|
|
|
case parser.NextIsWord(): return parser.ParseCommand()
|
|
|
- case parser.NextIsSet(): return parser.ParseSet()
|
|
|
- case parser.NextIsGet(): return parser.ParseGet()
|
|
|
- case parser.NextIsValue(): return parser.ParseCommand()
|
|
|
+ case parser.NextIsSubstitution(): return parser.ParseSubstitution()
|
|
|
+ case parser.NextIsLiteral(): return parser.ParseLiteral()
|
|
|
default:
|
|
|
parser.Panicf("Syntax error in expression, expected word, $, =, value")
|
|
|
return nil
|
|
@@ -502,8 +503,14 @@ func (parser Parser) NextIs(kinds ...TokenKind) bool {
|
|
|
return false
|
|
|
}
|
|
|
|
|
|
-func (parser Parser) NextIsClosed() bool {
|
|
|
- return parser.NextIs(TokenKindOpenBlock, TokenKindOpenList, TokenKindOpenParen)
|
|
|
+func (parser Parser) NextIsBlock() bool {
|
|
|
+ return parser.NextIs(TokenKindOpenBlock)
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+func (parser Parser) NextIsSubstitution() bool {
|
|
|
+ return parser.NextIs(TokenKindOpenList, TokenKindOpenParen,
|
|
|
+ TokenKindSet, TokenKindGet)
|
|
|
}
|
|
|
|
|
|
func (parser Parser) NextIsWord() bool {
|
|
@@ -518,29 +525,29 @@ func (parser Parser) NextIsSet() bool {
|
|
|
return parser.NextIs(TokenKindSet)
|
|
|
}
|
|
|
|
|
|
-func (parser Parser) NextIsValue() bool {
|
|
|
- return parser.NextIs(TokenKindString, TokenKindType,
|
|
|
- TokenKindInteger, TokenKindFloat, TokenKindBoolean, TokenKindNil,
|
|
|
- TokenKindSymbol)
|
|
|
+func (parser Parser) NextIsLiteral() bool {
|
|
|
+ return parser.NextIs(TokenKindString, TokenKindInteger, TokenKindFloat,
|
|
|
+ TokenKindBoolean, TokenKindNil)
|
|
|
+}
|
|
|
+
|
|
|
+func (parser Parser) NextIsName() bool {
|
|
|
+ return parser.NextIs(TokenKindWord, TokenKindType, TokenKindSymbol)
|
|
|
}
|
|
|
|
|
|
func (parser Parser) NextIsOperator() bool {
|
|
|
return parser.NextIs(TokenKindOperator)
|
|
|
}
|
|
|
|
|
|
-func (parser Parser) NextIsWordValue() bool {
|
|
|
- return parser.NextIs(TokenKindWord, TokenKindString, TokenKindType,
|
|
|
- TokenKindInteger, TokenKindFloat, TokenKindBoolean, TokenKindNil,
|
|
|
- TokenKindSymbol)
|
|
|
+func (parser Parser) NextIsArgument() bool {
|
|
|
+ return parser.NextIsName() || parser.NextIsLiteral() ||
|
|
|
+ parser.NextIsSubstitution() || parser.NextIsBlock()
|
|
|
}
|
|
|
|
|
|
-func (parser Parser) NextIsArgument() bool {
|
|
|
- return parser.NextIs(TokenKindOpenBlock, TokenKindOpenList, TokenKindOpenParen,
|
|
|
- TokenKindSet, TokenKindGet, TokenKindWord, TokenKindString, TokenKindType,
|
|
|
- TokenKindInteger, TokenKindFloat, TokenKindBoolean, TokenKindNil,
|
|
|
- TokenKindSymbol)
|
|
|
+func (parser Parser) NextIsCommand() bool {
|
|
|
+ return parser.NextIsName()
|
|
|
}
|
|
|
|
|
|
+
|
|
|
func (parser Parser) NextIsErrorSkipped() bool {
|
|
|
return parser.NextIs(TokenKindCloseBlock, TokenKindCloseList, TokenKindCloseParen,
|
|
|
TokenKindEOX, TokenKindEOF)
|
|
@@ -555,30 +562,71 @@ func (parser Parser) NextIsEOF() bool {
|
|
|
}
|
|
|
|
|
|
func (parser Parser) NextIsExpression() bool {
|
|
|
- return parser.NextIs(TokenKindWord,
|
|
|
- TokenKindGet,
|
|
|
- TokenKindSet,
|
|
|
- TokenKindString,
|
|
|
- TokenKindType,
|
|
|
- TokenKindInteger,
|
|
|
- TokenKindFloat,
|
|
|
- TokenKindBoolean, TokenKindNil,
|
|
|
- TokenKindSymbol)
|
|
|
+ return parser.NextIsCommand() || parser.NextIsSubstitution() ||
|
|
|
+ parser.NextIsLiteral()
|
|
|
+}
|
|
|
+
|
|
|
+func (parser Parser) NextIsChain() bool {
|
|
|
+ return parser.NextIsExpression()
|
|
|
}
|
|
|
|
|
|
+
|
|
|
func (parser Parser) NextIsStatement() bool {
|
|
|
- return parser.NextIsExpression() || parser.NextIsClosed() || parser.NextIsEOX()
|
|
|
+ return parser.NextIsChain() || parser.NextIsBlock() || parser.NextIsEOX()
|
|
|
}
|
|
|
|
|
|
+func (parser *Parser) ParseChain() *Ast {
|
|
|
+ expression := parser.ParseExpression()
|
|
|
+ if !parser.NextIsOperator() {
|
|
|
+ return expression
|
|
|
+ }
|
|
|
+
|
|
|
+ var expressions = []*Ast{ expression }
|
|
|
+ var operators = []Token {}
|
|
|
+ for parser.NextIsOperator() {
|
|
|
+ oper := parser.Require(TokenKindOperator)
|
|
|
+ expression := parser.ParseExpression()
|
|
|
+ if expression == nil {
|
|
|
+ parser.Panicf("Expected expression after operator.")
|
|
|
+ }
|
|
|
+ expressions = append(expressions, expression)
|
|
|
+ operators = append(operators, oper)
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ var chain *Ast
|
|
|
+
|
|
|
+ for i, j := len(expressions) - 1, len(operators) - 1 ; i >= 0 && j >= 0 ; i, j = i - 1 , j - 1 {
|
|
|
+ expression := expressions[i]
|
|
|
+ oper := operators[j]
|
|
|
+ if chain == nil {
|
|
|
+ expression2 := expressions[i-1]
|
|
|
+ subst2 := NewAstWithToken(AstKindParenthesis, oper)
|
|
|
+ subst2.AppendChildren(expression)
|
|
|
+ subst1 := NewAstWithToken(AstKindParenthesis, oper)
|
|
|
+ subst1.AppendChildren(expression2)
|
|
|
+ chain = NewAstWithToken(AstKindOperation, oper)
|
|
|
+ chain.AppendChildren(subst1, subst2)
|
|
|
+ i--
|
|
|
+ } else {
|
|
|
+ subst := NewAstWithToken(AstKindParenthesis, oper)
|
|
|
+ subst.AppendChildren(expression)
|
|
|
+ newChain := NewAstWithToken(AstKindOperation, oper)
|
|
|
+ newChain.AppendChildren(subst, chain)
|
|
|
+ chain = newChain
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return chain
|
|
|
+}
|
|
|
|
|
|
func (parser *Parser) ParseStatement() *Ast {
|
|
|
parser.LogDebug("ParseStatement: %s\n", parser.current.String())
|
|
|
switch {
|
|
|
- case parser.NextIsClosed(): return parser.ParseClosed()
|
|
|
- case parser.NextIsExpression(): return parser.ParseExpressionStatement()
|
|
|
+ case parser.NextIsBlock(): return parser.ParseBlock()
|
|
|
+ case parser.NextIsExpression(): return parser.ParseChain()
|
|
|
case parser.NextIsEOX(): return parser.ParseEmptyStatement()
|
|
|
default:
|
|
|
- parser.Panicf("Expected closed, expression, or EOX in statement")
|
|
|
+ parser.Panicf("Expected block, command, or EOX in statement")
|
|
|
return parser.NewAstError("Expected closed, expression, or EOX in statement")
|
|
|
}
|
|
|
}
|