@@ -80,6 +80,7 @@ namespace CodeGen.Engine
8080 private canonicalNameLookup, @Dictionary<string, string>, new Dictionary<string, string>()
8181
8282 private allowsExpressions, @HashSet<string>, new HashSet<string>()
83+ private expressionGlue, @HashSet<string>, new HashSet<string>()
8384
8485 private customValidity, @List<TokenValidity>
8586 private userTokenValidity, @List<TokenValidity>
@@ -1064,6 +1065,18 @@ namespace CodeGen.Engine
10641065 expressions.Add("VOID_SUBROUTINE", TokenValidity.MethodLoop)
10651066 expressions.Add("WEB", TokenValidity.FieldLoop | TokenValidity.KeySegmentLoop | TokenValidity.RelationSegmentLoop)
10661067
1068+ expressions.Add("AND", TokenValidity.Anywhere)
1069+ expressions.Add("OR", TokenValidity.Anywhere)
1070+ expressions.Add("NOT", TokenValidity.Anywhere)
1071+ expressions.Add("(", TokenValidity.Anywhere)
1072+ expressions.Add(")", TokenValidity.Anywhere)
1073+
1074+ expressionGlue.Add("AND")
1075+ expressionGlue.Add("OR")
1076+ expressionGlue.Add("NOT")
1077+ expressionGlue.Add("(")
1078+ expressionGlue.Add(")")
1079+
10671080 if (context != ^null)
10681081 begin
10691082 data define, string
@@ -1433,7 +1446,7 @@ namespace CodeGen.Engine
14331446
14341447 while (ix < templateCode.Length) do
14351448 begin
1436- data nextToken, @PossibleToken, nextPossibleToken(ix, templateCode)
1449+ data nextToken, @PossibleToken, nextPossibleToken(ix, templateCode, tokens.LastOrDefault() )
14371450
14381451 if (nextToken == ^null) then
14391452 begin
@@ -1450,8 +1463,8 @@ namespace CodeGen.Engine
14501463 ;; Is the token a closer?
14511464 data closer = nextTokenValue.StartsWith("/")
14521465
1453- ;; The next token isn't here, so we have just text. Add a Text token.
1454- if (nextToken.StartsAtPosition != ix)
1466+ ;; The next token isn't here, so we have just text. Add a Text token.
1467+ if (nextToken.StartsAtPosition != ix && nextToken.StartsAtPosition > ix )
14551468 tokens.Add(new Token(fileName, ix, nextToken.StartsAtPosition - 1, false, templateCode.Substring(ix, nextToken.StartsAtPosition - ix), TokenType.Text, TokenModifier.None, ^null, lineStarts, false, false))
14561469
14571470 if (nextToken.IsComment) then
@@ -1576,16 +1589,31 @@ namespace CodeGen.Engine
15761589 ix = nextToken.EndsAtPosition + 1
15771590
15781591 if (nextToken.IsExpression)
1579- begin
1580- data nextExpression, @Tuple<int, int, List<TokenValidity>>, nextExpressionToken(ix, templateCode)
1581- if (nextExpression != ^null)
1592+ begin
1593+ data expressionError = ""
1594+ data nextExpression, @Tuple<int, int, List<TokenValidity>>, nextExpressionToken(ix, templateCode, expressionError)
1595+ if(!string.IsNullOrWhiteSpace(expressionError) && !nextToken.IsCloser)
1596+ reportError(expressionError)
1597+ while (nextExpression != ^null)
15821598 begin
15831599 data expressionValue, string, templateCode.Substring(nextExpression.Item1, nextExpression.Item2 - nextExpression.Item1)
15841600 ;; TODO: Does this expression require repository structure processing?
1585- data requiresRps, boolean, false
1601+ data requiresRps, boolean, false
15861602 tokens.Add(new Token(fileName, nextExpression.Item1, nextExpression.Item2, false, expressionValue, TokenType.Expression, TokenModifier.None, nextExpression.Item3, lineStarts, requiresRps, false))
1587- ix = nextExpression.Item2 + 1
1588- end
1603+ if(expressionValue == '(' || expressionValue == ')' || templateCode[nextExpression.Item2] == ')') then
1604+ ix = nextExpression.Item2
1605+ else
1606+ begin
1607+ ix = nextExpression.Item2 + 1
1608+ if(templateCode[nextExpression.Item2] == '>')
1609+ exitloop
1610+ end
1611+
1612+ nextExpression = nextExpressionToken(ix, templateCode, expressionError)
1613+ end
1614+
1615+ if(ix < templateCode.Length && templateCode[ix] == '>')
1616+ incr ix
15891617 end
15901618
15911619 end
@@ -1663,21 +1691,22 @@ namespace CodeGen.Engine
16631691 ;;; <returns>PossibleToken instance, or null if no possible tokens found.</returns>
16641692 private method nextPossibleToken, @PossibleToken
16651693 searchFrom, int
1666- templateCode, string
1667- proc
1668- data foundPossibleToken = false
1694+ templateCode, string
1695+ lastToken, @Token
1696+ proc
1697+ data inTagTail = searchFrom > 0 && templateCode[searchFrom - 1] == '>'
1698+ data foundPossibleToken = !inTagTail && lastToken != ^null ? lastToken.TypeOfToken == TokenType.Expression : false
16691699 data isCloser = false
16701700 data isComment = false
1671- data isExpression = false
1672- data possibleTokenStartsAt, int, -1
1701+ data isExpression = foundPossibleToken
1702+ data possibleTokenStartsAt, int, foundPossibleToken ? searchFrom - 1 : -1
16731703
16741704 ;; Character by character looking for a token
16751705 data ix, int
16761706 for ix from searchFrom thru templateCode.Length - 1
16771707 begin
16781708 ;; Did we find a newline?
16791709 data foundNewLine, boolean, (((templateCode[ix] == %char(13)) && (templateCode.Length > ix + 1) && (templateCode[ix + 1] == %char(10))) || (templateCode[ix] == %char(10)))
1680-
16811710 ;; Did we find the start of a template file comment (;//)?
16821711 if (templateCode.Length > ix + 2 && templateCode[ix] == ';' && templateCode[ix + 1] == '/' && templateCode[ix + 2] == '/') then
16831712 begin
@@ -1713,7 +1742,7 @@ namespace CodeGen.Engine
17131742 isCloser = false
17141743 foundPossibleToken = true
17151744 possibleTokenStartsAt = ix
1716- end
1745+ end
17171746 end
17181747 else
17191748 begin
@@ -1736,8 +1765,9 @@ namespace CodeGen.Engine
17361765 begin
17371766 ;; So we found a > or a space after an <
17381767
1739- ;; Get the start and end indexes of the VALUE of the possible token (withoit the < > or " ")
1740- data realStartIndex, int, (possibleTokenStartsAt + 1)
1768+ ;; Get the start and end indexes of the VALUE of the possible token (withoit the < > or " ")
1769+ data skipStartLetter = templateCode[possibleTokenStartsAt] == '<' || templateCode[possibleTokenStartsAt] == ' '
1770+ data realStartIndex, int, skipStartLetter ? possibleTokenStartsAt + 1 : possibleTokenStartsAt
17411771 data realEndIndex, int, ix - 1
17421772 if (isCloser)
17431773 realStartIndex += 1
@@ -1854,7 +1884,8 @@ namespace CodeGen.Engine
18541884 ;;; <returns></returns>
18551885 private method nextExpressionToken, @Tuple<int, int, List<TokenValidity>>
18561886 startIndex, int
1857- templateCode, string
1887+ templateCode, string
1888+ out errorText, string
18581889 proc
18591890 data startedToken, boolean, false
18601891 data startedTokenIndex, int, -1
@@ -1864,19 +1895,21 @@ namespace CodeGen.Engine
18641895 begin
18651896 if (!startedToken) then
18661897 begin
1867- if (char.IsLetter(templateCode[ix]))
1898+ if (char.IsLetter(templateCode[ix])) then
18681899 begin
18691900 startedToken = true
18701901 startedTokenIndex = ix
1871- end
1902+ end
1903+ else if(templateCode[ix] == '(' || templateCode[ix] == ')')
1904+ mreturn Tuple.Create(ix, ix + 1, userTokenValidity)
18721905 end
18731906 else
1874- begin
1907+ begin
18751908 if (char.IsLetterOrDigit(templateCode[ix]) || (templateCode[ix] == '_')) then
18761909 begin
18771910 nextloop
18781911 end
1879- else if ((templateCode[ix] == ' ') || (templateCode[ix] == '>')) then
1912+ else if ((templateCode[ix] == ' ') || (templateCode[ix] == '>') || (templateCode[ix] == ')') ) then
18801913 begin
18811914 data expressionType, @List<TokenValidity>
18821915 data expstring, string, templateCode.Substring(startedTokenIndex, ix - startedTokenIndex)
@@ -1909,12 +1942,16 @@ namespace CodeGen.Engine
19091942 & || expstring.StartsWith("TOTAL_ITEMS_")) then
19101943 begin
19111944 mreturn Tuple.Create(startedTokenIndex, ix, loopUtilityTokenValidity)
1912- end
1945+ end
1946+ else if(expressionGlue.Contains(expstring)) then
1947+ begin
1948+ mreturn Tuple.Create(startedTokenIndex, ix, userTokenValidity)
1949+ end
19131950 else
19141951 begin
1915- ;; Invalid expression
1916- reportError( String.Format("Invalid expression <IF {0}> at offset {1}!", expstring, startedTokenIndex - 4, "") )
1917- exitloop
1952+ ;; Invalid expression
1953+ errorText = String.Format("Invalid expression <IF {0}> at offset {1}!", expstring, startedTokenIndex - 4, "")
1954+ mreturn ^null
19181955 end
19191956 end
19201957 else if (char.IsControl(templateCode[ix])) then
0 commit comments