mirror of
https://github.com/nim-lang/Nim.git
synced 2025-12-29 01:14:41 +00:00
allow multi-line expressions using the dot operator
this enables parsing of expressions like:
``` Nimrod
s.items
.map(proc (x): auto = x * 2)
.filter do (x) -> auto:
return x % 2 == 0
.group_by((x) => x.length)
```
This commit is contained in:
@@ -101,6 +101,7 @@ type
|
||||
base10, # base10 is listed as the first element,
|
||||
# so that it is the correct default value
|
||||
base2, base8, base16
|
||||
|
||||
TToken* = object # a Nimrod token
|
||||
tokType*: TTokType # the type of the token
|
||||
indent*: int # the indentation; != -1 if the token has been
|
||||
@@ -121,8 +122,9 @@ type
|
||||
indentAhead*: int # if > 0 an indendation has already been read
|
||||
# this is needed because scanning comments
|
||||
# needs so much look-ahead
|
||||
currLineIndent*: int
|
||||
strongSpaces*: bool
|
||||
|
||||
|
||||
|
||||
var gLinesCompiled*: int # all lines that have been compiled
|
||||
|
||||
@@ -206,6 +208,7 @@ proc openLexer(lex: var TLexer, fileIdx: int32, inputstream: PLLStream) =
|
||||
openBaseLexer(lex, inputstream)
|
||||
lex.fileIdx = fileidx
|
||||
lex.indentAhead = - 1
|
||||
lex.currLineIndent = 0
|
||||
inc(lex.lineNumber, inputstream.lineOffset)
|
||||
|
||||
proc closeLexer(lex: var TLexer) =
|
||||
@@ -709,6 +712,7 @@ proc skip(L: var TLexer, tok: var TToken) =
|
||||
tok.strongSpaceA = 0
|
||||
if buf[pos] > ' ':
|
||||
tok.indent = indent
|
||||
L.currLineIndent = indent
|
||||
break
|
||||
else:
|
||||
break # EndOfFile also leaves the loop
|
||||
@@ -718,6 +722,7 @@ proc rawGetTok(L: var TLexer, tok: var TToken) =
|
||||
fillToken(tok)
|
||||
if L.indentAhead >= 0:
|
||||
tok.indent = L.indentAhead
|
||||
L.currLineIndent = L.indentAhead
|
||||
L.indentAhead = -1
|
||||
else:
|
||||
tok.indent = -1
|
||||
@@ -827,5 +832,5 @@ proc rawGetTok(L: var TLexer, tok: var TToken) =
|
||||
tok.tokType = tkInvalid
|
||||
lexMessage(L, errInvalidToken, c & " (\\" & $(ord(c)) & ')')
|
||||
inc(L.bufpos)
|
||||
|
||||
|
||||
dummyIdent = getIdent("")
|
||||
|
||||
@@ -658,7 +658,7 @@ proc namedParams(p: var TParser, callee: PNode,
|
||||
exprColonEqExprListAux(p, endTok, result)
|
||||
|
||||
proc parseMacroColon(p: var TParser, x: PNode): PNode
|
||||
proc primarySuffix(p: var TParser, r: PNode): PNode =
|
||||
proc primarySuffix(p: var TParser, r: PNode, baseIndent: int): PNode =
|
||||
#| primarySuffix = '(' (exprColonEqExpr comma?)* ')' doBlocks?
|
||||
#| | doBlocks
|
||||
#| | '.' optInd ('type' | 'addr' | symbol) generalizedLit?
|
||||
@@ -666,7 +666,8 @@ proc primarySuffix(p: var TParser, r: PNode): PNode =
|
||||
#| | '{' optInd indexExprList optPar '}'
|
||||
#| | &( '`'|IDENT|literal|'cast') expr # command syntax
|
||||
result = r
|
||||
while p.tok.indent < 0:
|
||||
while p.tok.indent < 0 or
|
||||
(p.tok.tokType == tkDot and p.tok.indent >= baseIndent):
|
||||
case p.tok.tokType
|
||||
of tkParLe:
|
||||
if p.strongSpaces and p.tok.strongSpaceA > 0: break
|
||||
@@ -1007,8 +1008,9 @@ proc primary(p: var TParser, mode: TPrimaryMode): PNode =
|
||||
optInd(p, a)
|
||||
if isSigil:
|
||||
#XXX prefix operators
|
||||
let baseInd = p.lex.currLineIndent
|
||||
addSon(result, primary(p, pmSkipSuffix))
|
||||
result = primarySuffix(p, result)
|
||||
result = primarySuffix(p, result, baseInd)
|
||||
else:
|
||||
addSon(result, primary(p, pmNormal))
|
||||
return
|
||||
@@ -1071,9 +1073,10 @@ proc primary(p: var TParser, mode: TPrimaryMode): PNode =
|
||||
optInd(p, result)
|
||||
addSon(result, primary(p, pmNormal))
|
||||
else:
|
||||
let baseInd = p.lex.currLineIndent
|
||||
result = identOrLiteral(p, mode)
|
||||
if mode != pmSkipSuffix:
|
||||
result = primarySuffix(p, result)
|
||||
result = primarySuffix(p, result, baseInd)
|
||||
|
||||
proc parseTypeDesc(p: var TParser): PNode =
|
||||
#| typeDesc = simpleExpr
|
||||
@@ -1901,7 +1904,7 @@ proc parseStmt(p: var TParser): PNode =
|
||||
if p.tok.indent < 0 or p.tok.indent == p.currInd: discard
|
||||
else: break
|
||||
else:
|
||||
if p.tok.indent > p.currInd:
|
||||
if p.tok.indent > p.currInd and p.tok.tokType != tkDot:
|
||||
parMessage(p, errInvalidIndentation)
|
||||
break
|
||||
if p.tok.tokType in {tkCurlyRi, tkParRi, tkCurlyDotRi, tkBracketRi}:
|
||||
@@ -1928,7 +1931,8 @@ proc parseStmt(p: var TParser): PNode =
|
||||
else:
|
||||
result = newNodeP(nkStmtList, p)
|
||||
while true:
|
||||
if p.tok.indent >= 0: parMessage(p, errInvalidIndentation)
|
||||
if p.tok.indent >= 0:
|
||||
parMessage(p, errInvalidIndentation)
|
||||
let a = simpleStmt(p)
|
||||
if a.kind == nkEmpty: parMessage(p, errExprExpected, p.tok)
|
||||
result.add(a)
|
||||
|
||||
Reference in New Issue
Block a user