From 10ab814fbae0a54151028efd42ee9f806cc6bacd Mon Sep 17 00:00:00 2001 From: Andreas Rumpf Date: Wed, 16 Dec 2009 00:38:35 +0100 Subject: [PATCH] exprs for dynlib; indentation parsing --- doc/grammar.txt | 24 +++++++-------- doc/nimrodc.txt | 28 +++++++++++++++--- rod/pbraces.nim | 20 ++++++------- rod/pnimsyn.nim | 74 +++++++++++++++++++++------------------------- tests/tdllvar.nim | 16 ++++++++++ tests/tindent1.nim | 24 +++++++++++++++ 6 files changed, 119 insertions(+), 67 deletions(-) create mode 100755 tests/tdllvar.nim create mode 100755 tests/tindent1.nim diff --git a/doc/grammar.txt b/doc/grammar.txt index 8cb6fb8dc..3ce919b44 100755 --- a/doc/grammar.txt +++ b/doc/grammar.txt @@ -8,7 +8,7 @@ operator ::= OP0 | OR | XOR | AND | OP3 | OP4 | OP5 | OP6 | OP7 prefixOperator ::= OP0 | OP3 | OP4 | OP5 | OP6 | OP7 | 'not' optInd ::= [COMMENT] [IND] - +optPar ::= [IND] | [SAD] lowestExpr ::= orExpr (OP0 optInd orExpr)* orExpr ::= andExpr (OR | 'xor' optInd andExpr)* @@ -21,16 +21,16 @@ dollarExpr ::= primary (OP7 optInd primary)* indexExpr ::= '..' [expr] | expr ['=' expr | '..' expr] -castExpr ::= 'cast' '[' optInd typeDesc [SAD] ']' '(' optInd expr [SAD] ')' -addrExpr ::= 'addr' '(' optInd expr ')' +castExpr ::= 'cast' '[' optInd typeDesc optPar ']' '(' optInd expr optPar ')' +addrExpr ::= 'addr' '(' optInd expr optPar ')' symbol ::= '`' (KEYWORD | IDENT | operator | '(' ')' | '[' ']' | '=' | literal)+ '`' | IDENT primaryPrefix ::= (prefixOperator | 'bind') optInd primarySuffix ::= '.' optInd symbol - | '(' optInd namedExprList [SAD] ')' - | '[' optInd [indexExpr (comma indexExpr)* [comma]] [SAD] ']' + | '(' optInd namedExprList optPar ')' + | '[' optInd [indexExpr (comma indexExpr)* [comma]] optPar ']' | '^' | pragma @@ -44,9 +44,9 @@ literal ::= INT_LIT | INT8_LIT | INT16_LIT | INT32_LIT | INT64_LIT | NIL constructor ::= literal - | '[' optInd colonExprList [SAD] ']' - | '{' optInd sliceExprList [SAD] '}' - | '(' optInd colonExprList [SAD] ')' + | '[' optInd colonExprList optPar ']' + | '{' optInd sliceExprList optPar '}' + | '(' optInd colonExprList optPar ')' colonExpr ::= expr [':' expr] colonExprList ::= [colonExpr (comma colonExpr)* [comma]] @@ -128,13 +128,13 @@ importStmt ::= 'import' filename (comma filename)* includeStmt ::= 'include' filename (comma filename)* fromStmt ::= 'from' filename 'import' symbol (comma symbol)* -pragma ::= '{.' optInd (colonExpr [comma])* [SAD] ('.}' | '}') +pragma ::= '{.' optInd (colonExpr [comma])* optPar ('.}' | '}') param ::= symbol (comma symbol)* (':' typeDesc ['=' expr] | '=' expr) -paramList ::= ['(' [param (comma param)*] [SAD] ')'] [':' typeDesc] +paramList ::= ['(' [param (comma param)*] optPar ')'] [':' typeDesc] genericParam ::= symbol [':' typeDesc] ['=' expr] -genericParams ::= '[' genericParam (comma genericParam)* [SAD] ']' +genericParams ::= '[' genericParam (comma genericParam)* optPar ']' routineDecl := symbol ['*'] [genericParams] paramList [pragma] ['=' stmt] @@ -164,7 +164,7 @@ objectCase ::= 'case' expr ':' typeDesc [COMMENT] objectPart ::= objectWhen | objectCase | objectIdentPart | 'nil' | indPush objectPart (SAD objectPart)* DED indPop -tupleDesc ::= '[' optInd [param (comma param)*] [SAD] ']' +tupleDesc ::= '[' optInd [param (comma param)*] optPar ']' objectDef ::= 'object' [pragma] ['of' typeDesc] objectPart enumField ::= symbol ['=' expr] diff --git a/doc/nimrodc.txt b/doc/nimrodc.txt index 4a94bc8cf..3c83cf76c 100755 --- a/doc/nimrodc.txt +++ b/doc/nimrodc.txt @@ -118,17 +118,37 @@ The ``dynlib`` import mechanism supports a versioning scheme: .. code-block:: nimrod proc Tcl_Eval(interp: pTcl_Interp, script: cstring): int {.cdecl, - importc, dynlib: "libtcl(8.5|8.4|8.3).so.(1|0)".} + importc, dynlib: "libtcl(|8.5|8.4|8.3).so.(1|0)".} At runtime the dynamic library is searched for (in this order):: - libtcl8.5.so.1 - libtcl8.4.so.1 - libtcl8.3.so.1 + libtcl.so.1 + libtcl.so.0 + libtcl8.5.so.1 libtcl8.5.so.0 + libtcl8.4.so.1 libtcl8.4.so.0 + libtcl8.3.so.1 libtcl8.3.so.0 +The ``dynlib`` pragma supports not only constant strings as argument but also +string expressions in general: + +.. code-block:: nimrod + import os + + proc getDllName: string = + result = "mylib.dll" + if ExistsFile(result): return + result = "mylib2.dll" + if ExistsFile(result): return + quit("could not load dynamic library") + + proc myImport(s: cstring) {.cdecl, importc, dynlib: getDllName().} + +**Note**: Patterns like ``libtcl(|8.5|8.4).so`` are only supported in constant +strings, because they are precompiled. + NoDecl Pragma ~~~~~~~~~~~~~ diff --git a/rod/pbraces.nim b/rod/pbraces.nim index a53eae903..4a5f85b85 100755 --- a/rod/pbraces.nim +++ b/rod/pbraces.nim @@ -71,7 +71,7 @@ proc indexExprList(p: var TParser, first: PNode): PNode = if p.tok.tokType != tkComma: break getTok(p) optInd(p, a) - optSad(p) + optPar(p) eat(p, tkBracketRi) proc exprColonEqExpr(p: var TParser, kind: TNodeKind, tok: TTokType): PNode = @@ -133,7 +133,7 @@ proc exprColonEqExprListAux(p: var TParser, elemKind: TNodeKind, if p.tok.tokType != tkComma: break getTok(p) optInd(p, a) - optSad(p) + optPar(p) eat(p, endTok) proc exprColonEqExprList(p: var TParser, kind, elemKind: TNodeKind, @@ -147,12 +147,12 @@ proc parseCast(p: var TParser): PNode = eat(p, tkBracketLe) optInd(p, result) addSon(result, parseTypeDesc(p)) - optSad(p) + optPar(p) eat(p, tkBracketRi) eat(p, tkParLe) optInd(p, result) addSon(result, parseExpr(p)) - optSad(p) + optPar(p) eat(p, tkParRi) proc parseAddr(p: var TParser): PNode = @@ -161,7 +161,7 @@ proc parseAddr(p: var TParser): PNode = eat(p, tkParLe) optInd(p, result) addSon(result, parseExpr(p)) - optSad(p) + optPar(p) eat(p, tkParRi) proc identOrLiteral(p: var TParser): PNode = @@ -343,7 +343,7 @@ proc parsePragma(p: var TParser): PNode = if p.tok.tokType == tkComma: getTok(p) optInd(p, a) - optSad(p) + optPar(p) if (p.tok.tokType == tkCurlyDotRi) or (p.tok.tokType == tkCurlyRi): getTok(p) else: parMessage(p, errTokenExpected, ".}") @@ -416,7 +416,7 @@ proc parseTuple(p: var TParser): PNode = if p.tok.tokType != tkComma: break getTok(p) optInd(p, a) - optSad(p) + optPar(p) eat(p, tkBracketRi) proc parseParamList(p: var TParser): PNode = @@ -437,7 +437,7 @@ proc parseParamList(p: var TParser): PNode = if p.tok.tokType != tkComma: break getTok(p) optInd(p, a) - optSad(p) + optPar(p) eat(p, tkParRi) if p.tok.tokType == tkColon: getTok(p) @@ -801,7 +801,7 @@ proc parseGenericParamList(p: var TParser): PNode = if p.tok.tokType != tkComma: break getTok(p) optInd(p, a) - optSad(p) + optPar(p) eat(p, tkBracketRi) proc parseRoutine(p: var TParser, kind: TNodeKind): PNode = @@ -1061,7 +1061,7 @@ proc parseVarTuple(p: var TParser): PNode = getTok(p) optInd(p, a) addSon(result, nil) # no type desc - optSad(p) + optPar(p) eat(p, tkParRi) eat(p, tkEquals) optInd(p, result) diff --git a/rod/pnimsyn.nim b/rod/pnimsyn.nim index 27a02e829..21980ccc4 100755 --- a/rod/pnimsyn.nim +++ b/rod/pnimsyn.nim @@ -48,7 +48,7 @@ proc expectIdentOrOpr*(p: TParser) proc parLineInfo*(p: TParser): TLineInfo proc Eat*(p: var TParser, TokType: TTokType) proc skipInd*(p: var TParser) -proc optSad*(p: var TParser) +proc optPar*(p: var TParser) proc optInd*(p: var TParser, n: PNode) proc indAndComment*(p: var TParser, n: PNode) proc setBaseFlags*(n: PNode, base: TNumericalBase) @@ -61,18 +61,18 @@ proc initParser(p: var TParser) = new(p.tok) proc getTok(p: var TParser) = - rawGetTok(p.lex^ , p.tok^ ) + rawGetTok(p.lex^, p.tok^) proc OpenParser(p: var TParser, filename: string, inputStream: PLLStream) = initParser(p) - OpenLexer(p.lex^ , filename, inputstream) + OpenLexer(p.lex^, filename, inputstream) getTok(p) # read the first token proc CloseParser(p: var TParser) = - CloseLexer(p.lex^ ) + CloseLexer(p.lex^) proc parMessage(p: TParser, msg: TMsgKind, arg: string = "") = - lexMessage(p.lex^ , msg, arg) + lexMessage(p.lex^, msg, arg) proc skipComment(p: var TParser, node: PNode) = if p.tok.tokType == tkComment: @@ -86,8 +86,8 @@ proc skipComment(p: var TParser, node: PNode) = proc skipInd(p: var TParser) = if p.tok.tokType == tkInd: getTok(p) -proc optSad(p: var TParser) = - if p.tok.tokType == tkSad: getTok(p) +proc optPar(p: var TParser) = + if p.tok.tokType == tkSad or p.tok.tokType == tkInd: getTok(p) proc optInd(p: var TParser, n: PNode) = skipComment(p, n) @@ -95,22 +95,22 @@ proc optInd(p: var TParser, n: PNode) = proc expectIdentOrKeyw(p: TParser) = if (p.tok.tokType != tkSymbol) and not isKeyword(p.tok.tokType): - lexMessage(p.lex^ , errIdentifierExpected, tokToStr(p.tok)) + lexMessage(p.lex^, errIdentifierExpected, tokToStr(p.tok)) proc ExpectIdent(p: TParser) = if p.tok.tokType != tkSymbol: - lexMessage(p.lex^ , errIdentifierExpected, tokToStr(p.tok)) + lexMessage(p.lex^, errIdentifierExpected, tokToStr(p.tok)) proc expectIdentOrOpr(p: TParser) = if not (p.tok.tokType in tokOperators): - lexMessage(p.lex^ , errOperatorExpected, tokToStr(p.tok)) + lexMessage(p.lex^, errOperatorExpected, tokToStr(p.tok)) proc Eat(p: var TParser, TokType: TTokType) = if p.tok.TokType == TokType: getTok(p) - else: lexMessage(p.lex^ , errTokenExpected, TokTypeToStr[tokType]) + else: lexMessage(p.lex^, errTokenExpected, TokTypeToStr[tokType]) proc parLineInfo(p: TParser): TLineInfo = - result = getLineInfo(p.lex^ ) + result = getLineInfo(p.lex^) proc indAndComment(p: var TParser, n: PNode) = var info: TLineInfo @@ -123,7 +123,7 @@ proc indAndComment(p: var TParser, n: PNode) = skipComment(p, n) proc newNodeP(kind: TNodeKind, p: TParser): PNode = - result = newNodeI(kind, getLineInfo(p.lex^ )) + result = newNodeI(kind, getLineInfo(p.lex^)) proc newIntNodeP(kind: TNodeKind, intVal: BiggestInt, p: TParser): PNode = result = newNodeP(kind, p) @@ -166,9 +166,6 @@ proc isOperator(tok: PToken): bool = result = getPrecedence(tok) >= 0 proc parseSymbol(p: var TParser): PNode = - var - s: string - id: PIdent case p.tok.tokType of tkSymbol: result = newIdentNodeP(p.tok.ident, p) @@ -178,7 +175,7 @@ proc parseSymbol(p: var TParser): PNode = getTok(p) case p.tok.tokType of tkBracketLe: - s = "[" + var s = "[" getTok(p) if (p.tok.tokType == tkOpr) and (p.tok.ident.s == "$"): s = s & "$.." @@ -204,7 +201,7 @@ proc parseSymbol(p: var TParser): PNode = getTok(p) eat(p, tkParRi) of tokKeywordLow..tokKeywordHigh, tkSymbol, tkOpr: - id = p.tok.ident + var id = p.tok.ident getTok(p) if p.tok.tokType == tkEquals: addSon(result, newIdentNodeP(getIdent(id.s & '='), p)) @@ -283,24 +280,22 @@ proc indexExpr(p: var TParser): PNode = else: result = a proc indexExprList(p: var TParser, first: PNode): PNode = - var a: PNode result = newNodeP(nkBracketExpr, p) addSon(result, first) getTok(p) optInd(p, result) while (p.tok.tokType != tkBracketRi) and (p.tok.tokType != tkEof) and (p.tok.tokType != tkSad): - a = indexExpr(p) + var a = indexExpr(p) addSon(result, a) if p.tok.tokType != tkComma: break getTok(p) optInd(p, a) - optSad(p) + optPar(p) eat(p, tkBracketRi) proc exprColonEqExpr(p: var TParser, kind: TNodeKind, tok: TTokType): PNode = - var a: PNode - a = parseExpr(p) + var a = parseExpr(p) if p.tok.tokType == tok: result = newNodeP(kind, p) getTok(p) #optInd(p, result); @@ -311,11 +306,10 @@ proc exprColonEqExpr(p: var TParser, kind: TNodeKind, tok: TTokType): PNode = proc exprListAux(p: var TParser, elemKind: TNodeKind, endTok, sepTok: TTokType, result: PNode) = - var a: PNode getTok(p) optInd(p, result) while (p.tok.tokType != endTok) and (p.tok.tokType != tkEof): - a = exprColonEqExpr(p, elemKind, sepTok) + var a = exprColonEqExpr(p, elemKind, sepTok) addSon(result, a) if p.tok.tokType != tkComma: break getTok(p) @@ -323,22 +317,20 @@ proc exprListAux(p: var TParser, elemKind: TNodeKind, endTok, sepTok: TTokType, eat(p, endTok) proc qualifiedIdent(p: var TParser): PNode = - var a: PNode result = parseSymbol(p) #optInd(p, result); if p.tok.tokType == tkDot: getTok(p) optInd(p, result) - a = result + var a = result result = newNodeI(nkDotExpr, a.info) addSon(result, a) addSon(result, parseSymbol(p)) proc qualifiedIdentListAux(p: var TParser, endTok: TTokType, result: PNode) = - var a: PNode getTok(p) optInd(p, result) while (p.tok.tokType != endTok) and (p.tok.tokType != tkEof): - a = qualifiedIdent(p) + var a = qualifiedIdent(p) addSon(result, a) #optInd(p, a); if p.tok.tokType != tkComma: break getTok(p) @@ -347,17 +339,17 @@ proc qualifiedIdentListAux(p: var TParser, endTok: TTokType, result: PNode) = proc exprColonEqExprListAux(p: var TParser, elemKind: TNodeKind, endTok, sepTok: TTokType, result: PNode) = - var a: PNode + assert(endTok in {tkCurlyRi, tkCurlyDotRi, tkBracketRi, tkParRi}) getTok(p) optInd(p, result) while (p.tok.tokType != endTok) and (p.tok.tokType != tkEof) and - (p.tok.tokType != tkSad): - a = exprColonEqExpr(p, elemKind, sepTok) + (p.tok.tokType != tkSad) and (p.tok.tokType != tkInd): + var a = exprColonEqExpr(p, elemKind, sepTok) addSon(result, a) if p.tok.tokType != tkComma: break getTok(p) optInd(p, a) - optSad(p) + optPar(p) eat(p, endTok) proc exprColonEqExprList(p: var TParser, kind, elemKind: TNodeKind, @@ -371,12 +363,12 @@ proc parseCast(p: var TParser): PNode = eat(p, tkBracketLe) optInd(p, result) addSon(result, parseTypeDesc(p)) - optSad(p) + optPar(p) eat(p, tkBracketRi) eat(p, tkParLe) optInd(p, result) addSon(result, parseExpr(p)) - optSad(p) + optPar(p) eat(p, tkParRi) proc parseAddr(p: var TParser): PNode = @@ -385,7 +377,7 @@ proc parseAddr(p: var TParser): PNode = eat(p, tkParLe) optInd(p, result) addSon(result, parseExpr(p)) - optSad(p) + optPar(p) eat(p, tkParRi) proc setBaseFlags(n: PNode, base: TNumericalBase) = @@ -577,7 +569,7 @@ proc parsePragma(p: var TParser): PNode = if p.tok.tokType == tkComma: getTok(p) optInd(p, a) - optSad(p) + optPar(p) if (p.tok.tokType == tkCurlyDotRi) or (p.tok.tokType == tkCurlyRi): getTok(p) else: parMessage(p, errTokenExpected, ".}") @@ -650,7 +642,7 @@ proc parseTuple(p: var TParser): PNode = if p.tok.tokType != tkComma: break getTok(p) optInd(p, a) - optSad(p) + optPar(p) eat(p, tkBracketRi) proc parseParamList(p: var TParser): PNode = @@ -673,7 +665,7 @@ proc parseParamList(p: var TParser): PNode = if p.tok.tokType != tkComma: break getTok(p) optInd(p, a) - optSad(p) + optPar(p) eat(p, tkParRi) if p.tok.tokType == tkColon: getTok(p) @@ -1035,7 +1027,7 @@ proc parseGenericParamList(p: var TParser): PNode = if p.tok.tokType != tkComma: break getTok(p) optInd(p, a) - optSad(p) + optPar(p) eat(p, tkBracketRi) proc parseRoutine(p: var TParser, kind: TNodeKind): PNode = @@ -1283,7 +1275,7 @@ proc parseVarTuple(p: var TParser): PNode = getTok(p) optInd(p, a) addSon(result, nil) # no type desc - optSad(p) + optPar(p) eat(p, tkParRi) eat(p, tkEquals) optInd(p, result) diff --git a/tests/tdllvar.nim b/tests/tdllvar.nim new file mode 100755 index 000000000..ab767770c --- /dev/null +++ b/tests/tdllvar.nim @@ -0,0 +1,16 @@ +import os + +proc getDllName: string = + result = "mylib.dll" + if ExistsFile(result): return + result = "mylib2.dll" + if ExistsFile(result): return + quit("could not load dynamic library") + +proc myImport(s: cstring) {.cdecl, importc, dynlib: getDllName().} +proc myImport2(s: int) {.cdecl, importc, dynlib: getDllName().} + +myImport("test2") +myImport2(12) + + diff --git a/tests/tindent1.nim b/tests/tindent1.nim new file mode 100755 index 000000000..0527b6e57 --- /dev/null +++ b/tests/tindent1.nim @@ -0,0 +1,24 @@ + +const romanNumbers1 = + [ + ("M", 1000), ("D", 500), ("C", 100), + ("L", 50), ("X", 10), ("V", 5), ("I", 1) ] + +const romanNumbers2 = + [ + ("M", 1000), ("D", 500), ("C", 100), + ("L", 50), ("X", 10), ("V", 5), ("I", 1) + ] + +const romanNumbers3 = + [ + ("M", 1000), ("D", 500), ("C", 100), + ("L", 50), ("X", 10), ("V", 5), ("I", 1) + ] + +const romanNumbers4 = [ + ("M", 1000), ("D", 500), ("C", 100), + ("L", 50), ("X", 10), ("V", 5), ("I", 1) + ] + +