3838 inSemiStmtList: int
3939
4040proc parseAll * (p: var TParser ): PNode
41- proc openParser * (p: var TParser , filename: string , inputstream: PLLStream )
4241proc closeParser * (p: var TParser )
4342proc parseTopLevelStmt * (p: var TParser ): PNode
4443 # implements an iterator. Returns the next top-level statement or
@@ -50,7 +49,6 @@ proc parseString*(s: string, filename: string = "", line: int = 0): PNode
5049 # correct error messages referring to the original source.
5150
5251# helpers for the other parsers
53- proc getPrecedence * (tok: TToken ): int
5452proc isOperator * (tok: TToken ): bool
5553proc getTok * (p: var TParser )
5654proc parMessage * (p: TParser , msg: TMsgKind , arg: string = " " )
@@ -77,14 +75,17 @@ proc parseCase(p: var TParser): PNode
7775proc getTok (p: var TParser ) =
7876 rawGetTok (p.lex, p.tok)
7977
80- proc openParser * (p: var TParser , fileIdx: int32 , inputStream: PLLStream ) =
78+ proc openParser * (p: var TParser , fileIdx: int32 , inputStream: PLLStream ,
79+ strongSpaces= false ) =
8180 initToken (p.tok)
8281 openLexer (p.lex, fileIdx, inputStream)
8382 getTok (p) # read the first token
8483 p.firstTok = true
84+ p.strongSpaces = strongSpaces
8585
86- proc openParser * (p: var TParser , filename: string , inputStream: PLLStream ) =
87- openParser (p, filename.fileInfoIdx, inputstream)
86+ proc openParser * (p: var TParser , filename: string , inputStream: PLLStream ,
87+ strongSpaces= false ) =
88+ openParser (p, filename.fileInfoIdx, inputstream, strongSpaces)
8889
8990proc closeParser (p: var TParser ) =
9091 closeLexer (p.lex)
@@ -193,34 +194,52 @@ proc isSigilLike(tok: TToken): bool {.inline.} =
193194proc isLeftAssociative (tok: TToken ): bool {.inline .} =
194195 result = tok.tokType != tkOpr or relevantOprChar (tok.ident) != '^'
195196
196- proc getPrecedence (tok: TToken ): int =
197+ proc getPrecedence (tok: TToken , strongSpaces: bool ): int =
198+ template considerStrongSpaces (x): expr =
199+ x + (if strongSpaces: 100 - tok.strongSpaceA.int * 10 else : 0 )
200+
197201 case tok.tokType
198202 of tkOpr:
199203 let L = tok.ident.s.len
200204 let relevantChar = relevantOprChar (tok.ident)
201205
202- template considerAsgn (value: expr) =
203- result = if tok.ident.s[L- 1 ] == '=' : 1 else : value
206+ template considerAsgn (value: expr) =
207+ result = if tok.ident.s[L- 1 ] == '=' : 1 else : considerStrongSpaces ( value)
204208
205209 case relevantChar
206210 of '$' , '^' : considerAsgn (10 )
207211 of '*' , '%' , '/' , '\\ ' : considerAsgn (9 )
208- of '~' : result = 8
212+ of '~' : result = considerStrongSpaces ( 8 )
209213 of '+' , '-' , '|' : considerAsgn (8 )
210214 of '&' : considerAsgn (7 )
211- of '=' , '<' , '>' , '!' : result = 5
215+ of '=' , '<' , '>' , '!' : result = considerStrongSpaces ( 5 )
212216 of '.' : considerAsgn (6 )
213- of '?' : result = 2
217+ of '?' : result = considerStrongSpaces ( 2 )
214218 else : considerAsgn (2 )
215219 of tkDiv, tkMod, tkShl, tkShr: result = 9
216220 of tkIn, tkNotin, tkIs, tkIsnot, tkNot, tkOf, tkAs: result = 5
217- of tkDotDot: result = 6
221+ of tkDotDot: result = considerStrongSpaces ( 6 )
218222 of tkAnd: result = 4
219223 of tkOr, tkXor: result = 3
220- else : result = - 10
221-
222- proc isOperator (tok: TToken ): bool =
223- result = getPrecedence (tok) >= 0
224+ else : result = - 10
225+
226+ proc isOperator (tok: TToken ): bool =
227+ tok.tokType in {tkOpr, tkDiv, tkMod, tkShl, tkShr, tkIn, tkNotin, tkIs,
228+ tkIsnot, tkNot, tkOf, tkAs, tkDotDot, tkAnd, tkOr, tkXor}
229+
230+ proc isUnary (p: TParser ): bool =
231+ p.strongSpaces and p.tok.tokType in {tkOpr, tkDotDot} and
232+ p.tok.strongSpaceB == 0 and
233+ p.tok.strongSpaceA > 0
234+
235+ proc checkBinary (p: TParser ) {.inline .} =
236+ # we don't check '..' here as that's too annoying
237+ if p.strongSpaces and p.tok.tokType == tkOpr:
238+ if p.tok.strongSpaceB > 0 and p.tok.strongSpaceA != p.tok.strongSpaceB:
239+ parMessage (p, errGenerated, " number of spaces around '$#' not consistent" %
240+ prettyTok (p.tok))
241+ elif p.tok.strongSpaceA notin {0 ,1 ,2 ,4 ,8 }:
242+ parMessage (p, errGenerated, " number of spaces must be 0,1,2,4 or 8" )
224243
225244# | module = stmt ^* (';' / IND{=})
226245# |
@@ -650,6 +669,7 @@ proc primarySuffix(p: var TParser, r: PNode): PNode =
650669 while p.tok.indent < 0 :
651670 case p.tok.tokType
652671 of tkParLe:
672+ if p.strongSpaces and p.tok.strongSpaceA > 0 : break
653673 result = namedParams (p, result , nkCall, tkParRi)
654674 if result .len > 1 and result .sons[1 ].kind == nkExprColonExpr:
655675 result .kind = nkObjConstr
@@ -664,8 +684,10 @@ proc primarySuffix(p: var TParser, r: PNode): PNode =
664684 result = dotExpr (p, result )
665685 result = parseGStrLit (p, result )
666686 of tkBracketLe:
687+ if p.strongSpaces and p.tok.strongSpaceA > 0 : break
667688 result = namedParams (p, result , nkBracketExpr, tkBracketRi)
668689 of tkCurlyLe:
690+ if p.strongSpaces and p.tok.strongSpaceA > 0 : break
669691 result = namedParams (p, result , nkCurlyExpr, tkCurlyRi)
670692 of tkSymbol, tkAccent, tkIntLit.. tkCharLit, tkNil, tkCast:
671693 if p.inPragma == 0 :
@@ -695,10 +717,11 @@ proc primary(p: var TParser, mode: TPrimaryMode): PNode
695717proc simpleExprAux (p: var TParser , limit: int , mode: TPrimaryMode ): PNode =
696718 result = primary (p, mode)
697719 # expand while operators have priorities higher than 'limit'
698- var opPrec = getPrecedence (p.tok)
720+ var opPrec = getPrecedence (p.tok, p.strongSpaces )
699721 let modeB = if mode == pmTypeDef: pmTypeDesc else : mode
700722 # the operator itself must not start on a new line:
701- while opPrec >= limit and p.tok.indent < 0 :
723+ while opPrec >= limit and p.tok.indent < 0 and not isUnary (p):
724+ checkBinary (p)
702725 var leftAssoc = ord (isLeftAssociative (p.tok))
703726 var a = newNodeP (nkInfix, p)
704727 var opNode = newIdentNodeP (p.tok.ident, p) # skip operator:
@@ -710,7 +733,7 @@ proc simpleExprAux(p: var TParser, limit: int, mode: TPrimaryMode): PNode =
710733 addSon (a, result )
711734 addSon (a, b)
712735 result = a
713- opPrec = getPrecedence (p.tok)
736+ opPrec = getPrecedence (p.tok, p.strongSpaces )
714737
715738proc simpleExpr (p: var TParser , mode = pmNormal): PNode =
716739 result = simpleExprAux (p, - 1 , mode)
@@ -1933,7 +1956,9 @@ proc parseString(s: string, filename: string = "", line: int = 0): PNode =
19331956 stream.lineOffset = line
19341957
19351958 var parser: TParser
1936- openParser (parser, filename, stream)
1959+ # XXX for now the builtin 'parseStmt/Expr' functions do not know about strong
1960+ # spaces...
1961+ openParser (parser, filename, stream, false )
19371962
19381963 result = parser.parseAll
19391964 closeParser (parser)
0 commit comments