mirror of
https://github.com/nim-lang/Nim.git
synced 2026-02-18 17:08:32 +00:00
command syntax is allowed in expressions
This commit is contained in:
@@ -34,6 +34,7 @@ type
|
||||
firstTok: bool
|
||||
lex*: TLexer # the lexer that is used for parsing
|
||||
tok*: TToken # the current token
|
||||
inPragma: int
|
||||
|
||||
proc parseAll*(p: var TParser): PNode
|
||||
proc openParser*(p: var TParser, filename: string, inputstream: PLLStream)
|
||||
@@ -518,14 +519,14 @@ proc parsePar(p: var TParser): PNode =
|
||||
eat(p, tkParRi)
|
||||
|
||||
proc identOrLiteral(p: var TParser, mode: TPrimaryMode): PNode =
|
||||
#| literal = | INT_LIT | INT8_LIT | INT16_LIT | INT32_LIT | INT64_LIT
|
||||
#| | UINT_LIT | UINT8_LIT | UINT16_LIT | UINT32_LIT | UINT64_LIT
|
||||
#| | FLOAT_LIT | FLOAT32_LIT | FLOAT64_LIT
|
||||
#| | STR_LIT | RSTR_LIT | TRIPLESTR_LIT
|
||||
#| | CHAR_LIT
|
||||
#| | NIL
|
||||
#| generalizedLit = GENERALIZED_STR_LIT | GENERALIZED_TRIPLESTR_LIT
|
||||
#| identOrLiteral = generalizedLit | symbol
|
||||
#| | INT_LIT | INT8_LIT | INT16_LIT | INT32_LIT | INT64_LIT
|
||||
#| | UINT_LIT | UINT8_LIT | UINT16_LIT | UINT32_LIT | UINT64_LIT
|
||||
#| | FLOAT_LIT | FLOAT32_LIT | FLOAT64_LIT
|
||||
#| | STR_LIT | RSTR_LIT | TRIPLESTR_LIT
|
||||
#| | CHAR_LIT
|
||||
#| | NIL
|
||||
#| identOrLiteral = generalizedLit | symbol | literal
|
||||
#| | par | arrayConstr | setOrTableConstr
|
||||
#| | castExpr
|
||||
#| tupleConstr = '(' optInd (exprColonEqExpr comma?)* optPar ')'
|
||||
@@ -634,12 +635,15 @@ proc namedParams(p: var TParser, callee: PNode,
|
||||
addSon(result, a)
|
||||
exprColonEqExprListAux(p, endTok, result)
|
||||
|
||||
proc parseMacroColon(p: var TParser, x: PNode): PNode
|
||||
proc primarySuffix(p: var TParser, r: PNode): PNode =
|
||||
#| primarySuffix = '(' (exprColonEqExpr comma?)* ')' doBlocks?
|
||||
#| | doBlocks
|
||||
#| | '.' optInd ('type' | 'addr' | symbol) generalizedLit?
|
||||
#| | '[' optInd indexExprList optPar ']'
|
||||
#| | '{' optInd indexExprList optPar '}'
|
||||
#| | &( '`'|IDENT|literal|'cast') expr ^+ ',' # command syntax
|
||||
#| (doBlock | macroColon)?
|
||||
result = r
|
||||
while p.tok.indent < 0:
|
||||
case p.tok.tokType
|
||||
@@ -661,8 +665,27 @@ proc primarySuffix(p: var TParser, r: PNode): PNode =
|
||||
result = namedParams(p, result, nkBracketExpr, tkBracketRi)
|
||||
of tkCurlyLe:
|
||||
result = namedParams(p, result, nkCurlyExpr, tkCurlyRi)
|
||||
else: break
|
||||
|
||||
of tkSymbol, tkAccent, tkIntLit..tkCharLit, tkNil, tkCast:
|
||||
if p.inPragma == 0:
|
||||
# actually parsing {.push hints:off.} as {.push(hints:off).} is a sweet
|
||||
# solution, but pragmas.nim can't handle that
|
||||
let a = result
|
||||
result = newNodeP(nkCommand, p)
|
||||
addSon(result, a)
|
||||
while p.tok.tokType != tkEof:
|
||||
let a = parseExpr(p)
|
||||
addSon(result, a)
|
||||
if p.tok.tokType != tkComma: break
|
||||
getTok(p)
|
||||
optInd(p, a)
|
||||
if p.tok.tokType == tkDo:
|
||||
parseDoBlocks(p, result)
|
||||
else:
|
||||
result = parseMacroColon(p, result)
|
||||
break
|
||||
else:
|
||||
break
|
||||
|
||||
proc primary(p: var TParser, mode: TPrimaryMode): PNode
|
||||
|
||||
proc simpleExprAux(p: var TParser, limit: int, mode: TPrimaryMode): PNode =
|
||||
@@ -713,6 +736,7 @@ proc parseIfExpr(p: var TParser, kind: TNodeKind): PNode =
|
||||
proc parsePragma(p: var TParser): PNode =
|
||||
#| pragma = '{.' optInd (exprColonExpr comma?)* optPar ('.}' | '}')
|
||||
result = newNodeP(nkPragma, p)
|
||||
inc p.inPragma
|
||||
getTok(p)
|
||||
optInd(p, result)
|
||||
while p.tok.tokType notin {tkCurlyDotRi, tkCurlyRi, tkEof}:
|
||||
@@ -724,6 +748,7 @@ proc parsePragma(p: var TParser): PNode =
|
||||
optPar(p)
|
||||
if p.tok.tokType in {tkCurlyDotRi, tkCurlyRi}: getTok(p)
|
||||
else: parMessage(p, errTokenExpected, ".}")
|
||||
dec p.inPragma
|
||||
|
||||
proc identVis(p: var TParser): PNode =
|
||||
#| identVis = symbol opr? # postfix position
|
||||
@@ -1031,15 +1056,50 @@ proc makeCall(n: PNode): PNode =
|
||||
result = newNodeI(nkCall, n.info)
|
||||
result.add n
|
||||
|
||||
proc parseMacroColon(p: var TParser, x: PNode): PNode =
|
||||
#| macroColon = ':' stmt? ( IND{=} 'of' exprList ':' stmt
|
||||
#| | IND{=} 'elif' expr ':' stmt
|
||||
#| | IND{=} 'except' exprList ':' stmt
|
||||
#| | IND{=} 'else' ':' stmt )*
|
||||
result = x
|
||||
if p.tok.tokType == tkColon and p.tok.indent < 0:
|
||||
result = makeCall(result)
|
||||
getTok(p)
|
||||
skipComment(p, result)
|
||||
if p.tok.tokType notin {tkOf, tkElif, tkElse, tkExcept}:
|
||||
let body = parseStmt(p)
|
||||
addSon(result, newProcNode(nkDo, body.info, body))
|
||||
while sameInd(p):
|
||||
var b: PNode
|
||||
case p.tok.tokType
|
||||
of tkOf:
|
||||
b = newNodeP(nkOfBranch, p)
|
||||
exprList(p, tkColon, b)
|
||||
of tkElif:
|
||||
b = newNodeP(nkElifBranch, p)
|
||||
getTok(p)
|
||||
optInd(p, b)
|
||||
addSon(b, parseExpr(p))
|
||||
eat(p, tkColon)
|
||||
of tkExcept:
|
||||
b = newNodeP(nkExceptBranch, p)
|
||||
exprList(p, tkColon, b)
|
||||
skipComment(p, b)
|
||||
of tkElse:
|
||||
b = newNodeP(nkElse, p)
|
||||
getTok(p)
|
||||
eat(p, tkColon)
|
||||
else: break
|
||||
addSon(b, parseStmt(p))
|
||||
addSon(result, b)
|
||||
if b.kind == nkElse: break
|
||||
|
||||
proc parseExprStmt(p: var TParser): PNode =
|
||||
#| exprStmt = simpleExpr
|
||||
#| (( '=' optInd expr )
|
||||
#| / ( expr ^+ comma
|
||||
#| doBlocks
|
||||
#| / ':' stmt? ( IND{=} 'of' exprList ':' stmt
|
||||
#| | IND{=} 'elif' expr ':' stmt
|
||||
#| | IND{=} 'except' exprList ':' stmt
|
||||
#| | IND{=} 'else' ':' stmt )*
|
||||
#| / macroColon
|
||||
#| ))?
|
||||
var a = simpleExpr(p)
|
||||
if p.tok.tokType == tkEquals:
|
||||
@@ -1064,37 +1124,7 @@ proc parseExprStmt(p: var TParser): PNode =
|
||||
result = makeCall(result)
|
||||
parseDoBlocks(p, result)
|
||||
return result
|
||||
if p.tok.tokType == tkColon and p.tok.indent < 0:
|
||||
result = makeCall(result)
|
||||
getTok(p)
|
||||
skipComment(p, result)
|
||||
if p.tok.tokType notin {tkOf, tkElif, tkElse, tkExcept}:
|
||||
let body = parseStmt(p)
|
||||
addSon(result, newProcNode(nkDo, body.info, body))
|
||||
while sameInd(p):
|
||||
var b: PNode
|
||||
case p.tok.tokType
|
||||
of tkOf:
|
||||
b = newNodeP(nkOfBranch, p)
|
||||
exprList(p, tkColon, b)
|
||||
of tkElif:
|
||||
b = newNodeP(nkElifBranch, p)
|
||||
getTok(p)
|
||||
optInd(p, b)
|
||||
addSon(b, parseExpr(p))
|
||||
eat(p, tkColon)
|
||||
of tkExcept:
|
||||
b = newNodeP(nkExceptBranch, p)
|
||||
exprList(p, tkColon, b)
|
||||
skipComment(p, b)
|
||||
of tkElse:
|
||||
b = newNodeP(nkElse, p)
|
||||
getTok(p)
|
||||
eat(p, tkColon)
|
||||
else: break
|
||||
addSon(b, parseStmt(p))
|
||||
addSon(result, b)
|
||||
if b.kind == nkElse: break
|
||||
result = parseMacroColon(p, result)
|
||||
|
||||
proc parseModuleName(p: var TParser, kind: TNodeKind): PNode =
|
||||
result = parseExpr(p)
|
||||
|
||||
12
tests/parser/tcommand_as_expr.nim
Normal file
12
tests/parser/tcommand_as_expr.nim
Normal file
@@ -0,0 +1,12 @@
|
||||
discard """
|
||||
output: "12"
|
||||
"""
|
||||
|
||||
proc foo(x: int): int = x-1
|
||||
proc foo(x, y: int): int = x-y
|
||||
|
||||
let x = foo 7.foo, # comment here
|
||||
foo(1, foo 8)
|
||||
# 12 = 6 - -6
|
||||
echo x
|
||||
|
||||
@@ -28,8 +28,8 @@ Changes affecting backwards compatibility
|
||||
require an error code to be passed to them. This error code can be retrieved
|
||||
using the new ``OSLastError`` proc.
|
||||
- ``os.parentDir`` now returns "" if there is no parent dir.
|
||||
- In CGI scripts stacktraces are shown user only if cgi.setStackTraceStdout
|
||||
is used.
|
||||
- In CGI scripts stacktraces are shown to the user only
|
||||
if ``cgi.setStackTraceStdout`` is used.
|
||||
- The symbol binding rules for clean templates changed: ``bind`` for any
|
||||
symbol that's not a parameter is now the default. ``mixin`` can be used
|
||||
to require instantiation scope for a symbol.
|
||||
@@ -71,8 +71,9 @@ Language Additions
|
||||
- Added a new ``delegator pragma`` for handling calls to missing procs and
|
||||
fields at compile-time.
|
||||
- The overload resolution now supports ``static[T]`` params that must be
|
||||
evaluatable at compile-time.
|
||||
evaluable at compile-time.
|
||||
- Support for user-defined type classes has been added.
|
||||
- The *command syntax* is supported in a lot more contexts.
|
||||
|
||||
|
||||
Tools improvements
|
||||
|
||||
Reference in New Issue
Block a user