diff options
author | Zahary Karadjov <zahary@gmail.com> | 2014-03-15 10:50:14 +0200 |
---|---|---|
committer | Zahary Karadjov <zahary@gmail.com> | 2014-03-16 20:42:06 +0200 |
commit | 7080d02af47cdc459aa441baa76d06f32af2f1c3 (patch) | |
tree | 101b23f4265fa9d1c20d2938b07bc6ee00bc24ad /compiler | |
parent | 63d93ad1ab6d491d8fdf4bdb7f958a21e89c2785 (diff) | |
download | Nim-7080d02af47cdc459aa441baa76d06f32af2f1c3.tar.gz |
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) ```
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/lexer.nim | 9 | ||||
-rw-r--r-- | compiler/parser.nim | 16 |
2 files changed, 17 insertions, 8 deletions
diff --git a/compiler/lexer.nim b/compiler/lexer.nim index 9c6c5e22f..be152eb55 100644 --- a/compiler/lexer.nim +++ b/compiler/lexer.nim @@ -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("") diff --git a/compiler/parser.nim b/compiler/parser.nim index 4ef5a300c..060629518 100644 --- a/compiler/parser.nim +++ b/compiler/parser.nim @@ -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) |