Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Added facilities for LexicalInfo. #5

Closed
wants to merge 6 commits into from

1 participant

@MaximTrushin

I added facilities for LexicalInfo. I hope I'm moving in the right direction.
Also OMetaInputWithMemo is improved as it is used more actively now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Aug 24, 2011
  1. @MaximTrushin
Commits on Oct 28, 2011
  1. @MaximTrushin

    Added facilities for LexicalInfo.

    MaximTrushin authored
    Improvements for OMetaInputWithMemo.
Commits on Nov 2, 2011
  1. @MaximTrushin
  2. @MaximTrushin

    Changed target .Net version.

    MaximTrushin authored
    Boo references are changed to relative paths.
    Removing version of NUnit in references.
  3. @MaximTrushin
Commits on Nov 3, 2011
  1. @MaximTrushin

    Saving start of a token in every token.

    MaximTrushin authored
    Using the saved value to track SourceLocation in some scenarios.
This page is out of date. Refresh to see the latest.
View
1  .gitignore
@@ -4,3 +4,4 @@ build.properties
*.pidb
*.userprefs
test-results
+obj
View
4 src/Boo.Adt/Boo.Adt.booproj
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ProjectGuid>{18AF07E6-C62E-4CDC-8F58-5A0F9A872F7F}</ProjectGuid>
@@ -7,7 +7,7 @@
<OutputType>Library</OutputType>
<RootNamespace>Boo.Adt</RootNamespace>
<AssemblyName>Boo.Adt</AssemblyName>
- <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
+ <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<ProductVersion>9.0.21022</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<UsePartialTypes>false</UsePartialTypes>
View
32 src/Boo.OMeta.Parser.Tests/BooParserTestFixture.boo
@@ -22,7 +22,37 @@ partial class BooParserTestFixture:
assert m.Documentation is not null
Assert.AreEqual(normalize(m.Documentation), normalize(m.ToCodeString()))
assert input.IsEmpty, input.ToString()
-
+
+
+ [Test]
+ def TestEndSourceLocationForInlineClosures():
+ code = """foo = { a = 3;
+return a; }"""
+ EnsureClosureEndSourceLocation(code, 2, 11)
+
+
+ [Test]
+ def TestEndSourceLocationForBlockClosures():
+ code = """
+foo = def():
+ return a
+"""
+ EnsureClosureEndSourceLocation(code, 3, 13)
+
+
+ def EnsureClosureEndSourceLocation(code as string, line as int, column as int):
+ parser = BooParser()
+
+ match parser.module(code):
+ case SuccessfulMatch(Input: input, Value: m=Module()):
+ assert m is not null
+ assert input.IsEmpty, input.ToString()
+ e = (m.Globals.Statements[0] as ExpressionStatement).Expression
+ cbe = (e as BinaryExpression).Right as BlockExpression
+ esl = cbe.Body.EndSourceLocation
+ Assert.AreEqual(line, esl.Line)
+ Assert.AreEqual(column, esl.Column)
+
def normalize(s as string):
return s.Trim().Replace("\r\n", "\n")
View
45 src/Boo.OMeta.Parser/AST.boo
@@ -358,10 +358,13 @@ def newStringInterpolation(items as List):
def newConditionalExpression(condition, trueValue, falseValue):
return ConditionalExpression(Condition: condition, TrueValue: trueValue, FalseValue: falseValue)
-def newBlockExpression(parameters as List, body):
+def newBlockExpression(start as OMetaInput, end as OMetaInput, parameters as List, body):
node = BlockExpression(Body: body)
for p in parameters[0]:
node.Parameters.Add(p)
+
+ node.EndSourceLocation = LexicalInfo("", getLine(end), getColumn(end))
+
return node
def newTypeofExpression(type):
@@ -439,8 +442,12 @@ def binaryOperatorFor(op):
def newAssignment(l as Expression, r as Expression):
return [| $l = $r |]
-
-def newBlock(contents, doc):
+
+def newBlock(start as OMetaInput, end as OMetaInput, contents, doc):
+/*
+start - first symbol of the block
+end - last symbol of the block
+*/
b = Block()
match contents:
case Statement():
@@ -450,8 +457,23 @@ def newBlock(contents, doc):
if item:
b.Statements.Add(item)
b.Documentation = doc
+ end = findPrevCharInput(end)
+ b.EndSourceLocation = LexicalInfo("", getLine(end), getColumn(end) + 1)//EndSourceLocation is the next symbol after the expression
+
return b
+def findPrevCharInput(input as OMetaInput):
+ while input:
+ if isCharInput(input): return input
+ input = input.Prev
+ return null
+
+def isCharInput(input as OMetaInput):
+ if input.IsEmpty or (not input.Head isa char): return false
+ if input.Head == char('\n') or input.Head == char('\r'): return false
+ return true
+
+
def prepend(first, tail as List):
if first is null: return tail
return [first] + tail
@@ -501,4 +523,19 @@ def checkEnumerableTypeShortcut(type, stars as List):
(enumerable as GenericTypeReference).GenericArguments.Add(type)
type = enumerable
return enumerable
-
+
+def getLine(input as OMetaInput):
+ if input:
+ return input.GetMemo("line") or 1
+ else:
+ return -1
+
+def getColumn(input as OMetaInput):
+ if input:
+ return input.Position - getLineStart(input) + 1 //Columns enumeration starts from 1
+ else:
+ return -1
+
+
+def getLineStart(input as OMetaInput):
+ return (input.GetMemo("lineStart") or 1) cast int
View
12 src/Boo.OMeta.Parser/Boo.OMeta.Parser.booproj
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ProjectGuid>{5A702DAA-43C7-45FF-9A9E-7A334FD75DD9}</ProjectGuid>
@@ -7,7 +7,7 @@
<OutputType>Library</OutputType>
<RootNamespace>Boo.OMeta.Parser</RootNamespace>
<AssemblyName>Boo.OMeta.Parser</AssemblyName>
- <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
+ <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<TargetFrameworkProfile />
<ProductVersion>10.0.0</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
@@ -45,6 +45,12 @@
<genwarnings>false</genwarnings>
</PropertyGroup>
<ItemGroup>
+ <Reference Include="Boo.Lang">
+ <HintPath>..\..\..\boo\build\Boo.Lang.dll</HintPath>
+ </Reference>
+ <Reference Include="Boo.Lang.Useful">
+ <HintPath>..\..\..\boo\build\Boo.Lang.Useful.dll</HintPath>
+ </Reference>
<Reference Include="System.Core">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
@@ -54,8 +60,6 @@
<Reference Include="System.Xml.Linq">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
- <Reference Include="Boo.Lang.Useful, Version=2.0.9.5, Culture=neutral, PublicKeyToken=32c39770e9a21a67" />
- <Reference Include="Boo.Lang, Version=2.0.9.5, Culture=neutral, PublicKeyToken=32c39770e9a21a67" />
</ItemGroup>
<ItemGroup>
<Compile Include="AssemblyInfo.boo" />
View
31 src/Boo.OMeta.Parser/BooParser.boo
@@ -100,6 +100,9 @@ ometa BooParser < WhitespaceSensitiveTokenizer:
space = line_continuation | multi_line_comment | line_comment | super
+ here = "" ^ makeToken("here", null, input, input)
+ prev = "" ^ makeToken("prev", null, input.Prev, input.Prev)
+
sqs = (SQ, --( sqs_esc | (~('\'' | '\\' | '\r' | '\n'), _)) >> s, SQ) ^ makeString(s)
dqs = (DQ, --( dqs_esc | (~('"' | '\\' | '\r' | '\n'), _)) >> s, DQ) ^ makeString(s)
@@ -335,15 +338,15 @@ ometa BooParser < WhitespaceSensitiveTokenizer:
empty_block = (begin_block, (PASS, eol), end_block) ^ Block()
- multi_line_block = ((begin_block_with_doc >> doc | begin_block), ++stmt >> stmts, end_block) ^ newBlock(stmts, doc)
+ multi_line_block = (here >> start, (begin_block_with_doc >> doc | begin_block), ++stmt >> stmts, end_block) ^ newBlock(getStart(start), input, stmts, doc)
macro_block = empty_block | multi_line_macro_block
- multi_line_macro_block = ((begin_block_with_doc >> doc | begin_block), ++(stmt | type_member_stmt) >> stmts, end_block) ^ newBlock(stmts, doc)
+ multi_line_macro_block = (here >> start, (begin_block_with_doc >> doc | begin_block), ++(stmt | type_member_stmt) >> stmts, end_block) ^ newBlock(getStart(start), input, stmts, doc)
type_member_stmt = (type_def | method) >> tm ^ TypeMemberStatement(TypeMember: tm)
- single_line_block = (COLON, stmt_line >> line) ^ newBlock(line, null)
+ single_line_block = (COLON >> start, stmt_line >> line) ^ newBlock(getStart(start), input, line, null)
begin_block = COLON, INDENT
@@ -416,7 +419,7 @@ ometa BooParser < WhitespaceSensitiveTokenizer:
stmt_unless = (UNLESS, assignment >> e, block >> condition) ^ newUnlessStatement(e, condition)
- false_block = ((ELIF, assignment >> e, block >> trueBlock, false_block >> falseBlock) ^ newBlock(newIfStatement(e, trueBlock, falseBlock), null)) | \
+ false_block = ((ELIF >> start, assignment >> e, block >> trueBlock, false_block >> falseBlock) ^ newBlock(getStart(start), input, newIfStatement(e, trueBlock, falseBlock), null)) | \
((ELSE, block >> falseBlock) ^ falseBlock) | ( "" ^ null)
stmt_return = (
@@ -430,12 +433,12 @@ ometa BooParser < WhitespaceSensitiveTokenizer:
block_expression = invocation_with_block | closure_block | dsl_friendly_invocation
invocation_with_block = (member_reference >> e and (e isa MethodInvocationExpression), \
- (closure_block | (block >> b ^ newBlockExpression([[], null], b))) >> c ^ newInvocationWithBlock(e, c) )
+ (closure_block | (here >> start, block >> b ^ newBlockExpression(getStart(start), input, [[], null], b))) >> c ^ newInvocationWithBlock(e, c) )
dsl_friendly_invocation = (member_reference >> e and ((e isa MemberReferenceExpression) or (e isa ReferenceExpression)), \
(block) >> c) ^ newInvocation(e, [BlockExpression(Body: c)], null)
- closure_block = ((DEF | DO), optional_parameters >> parameters, block >> body) ^ newBlockExpression(parameters, body)
+ closure_block = ((DEF | DO) >> start, optional_parameters >> parameters, block >> body) ^ newBlockExpression(getStart(start), getMemoEnd(input), parameters, body)
optional_parameters = method_parameters | ("" ^ [[], null])
@@ -598,7 +601,7 @@ ometa BooParser < WhitespaceSensitiveTokenizer:
type_literal = (TYPEOF, LPAREN, type_reference >> type, RPAREN) ^ newTypeofExpression(type)
- closure = (LBRACE, closure_parameters >> parameters, closure_stmt_list >> body, RBRACE) ^ newBlockExpression(parameters, newBlock(body, null))
+ closure = (LBRACE >> start, closure_parameters >> parameters, (closure_stmt_list >> body ), RBRACE >> end ^ newBlock(getStart(start), getStart(end).Prev, body, null)) >> body ^ newBlockExpression(getStart(start), input, parameters, body)
closure_parameters = ((optional_parameter_list >> parameters, BITWISE_OR) ^ [parameters, null]) | ("" ^ [[],null])
@@ -710,3 +713,17 @@ ometa BooParser < WhitespaceSensitiveTokenizer:
eol = (++EOL | ~_) ^ null
+ def getStart(token as Token):
+ if token:
+ return token.start
+ else:
+ return null
+
+ def getEnd(token as Token):
+ if token:
+ return token.end
+ else:
+ return null
+
+
+
View
114 src/Boo.OMeta.Parser/WhitespaceSensitiveTokenizer.boo
@@ -3,9 +3,46 @@ namespace Boo.OMeta.Parser
import System.Text
import Boo.OMeta
import Boo.Lang.PatternMatching
-import Boo.Adt
+//import Boo.Adt
+
+public class Token(object):
+
+ public final kind as string
+
+ public final value as string
+
+ public final start as OMetaInput
+
+ public final end as OMetaInput
+
+ public override def ToString() as string:
+ return "Token($(self.kind), $(self.value))"
+
+ public override def Equals(o as object) as bool:
+ if o is null:
+ return false
+ if self.GetType() is not o.GetType():
+ return false
+ other as Token = o
+ if string.op_Inequality(self.kind, other.kind):
+ return false
+ if string.op_Inequality(self.value, other.value):
+ return false
+ return true
+
+ public def constructor(kind as string, value as string):
+ super()
+ self.kind = kind
+ self.value = value
+
+ public def constructor(kind as string, value as string, start as OMetaInput, end as OMetaInput):
+ super()
+ self.kind = kind
+ self.value = value
+ self.start = start
+ self.end = end
+
-data Token(kind as string, value as string)
ometa WhitespaceSensitiveTokenizer():
@@ -31,22 +68,19 @@ ometa WhitespaceSensitiveTokenizer():
http://docs.python.org/ref/indentation.html
*/
- scanner = (
- (
- (((_ >> t) and (t isa Token)) ^ t) // token introduced by processDedent
+ scanner = ( (((_ >> t) and (t isa Token)) ^ t) // token introduced by processDedent
| (((indentation >> i) and sameIndent(input, i)) ^ makeToken("eol"))
- | (((indentation >> i) and largerIndent(input, i), $(processIndent(input, i))) >> value ^ value)
- | (((indentation >> i) and smallerIndent(input, i), $(processDedent(input, i)) >> value) ^ value)
+ | ((indentation >> i) and largerIndent(input, i), $(processIndent(input, i)))
+ | ((indentation >> i) and smallerIndent(input, i), $(processDedent(input, i)))
| ((--space, tokens >> t) ^ t)
- ) >> value
- ) ^ value
+ )
indentation = empty_lines, spaces
- empty_lines = ~~empty_line, ++empty_line
+ empty_lines = ++empty_line
empty_line = spaces, newline
spaces = --space >> value ^ value
space = ' ' | '\t' | (newline and inWSA(input))
- newline = '\n' | "\r\n" | "\r"
+ newline = '\n' | "\r\n" | "\r", $(newLine(input))
token[expected] = (scanner >> t and tokenMatches(t, expected)) ^ t
wsa = ~~_ and inWSA(input)
@@ -77,7 +111,10 @@ ometa WhitespaceSensitiveTokenizer():
return wsaLevel(input, wsaLevel(input) - 1)
def success(input as OMetaInput):
- return SuccessfulMatch(input, null)
+ return success(input, null)
+
+ def success(input as OMetaInput, value):
+ return SuccessfulMatch(input, value)
def indentStack(input as OMetaInput) as List:
return input.GetMemo("indentStack") or [0]
@@ -91,12 +128,16 @@ ometa WhitespaceSensitiveTokenizer():
def largerIndent(input as OMetaInput, i):
if len(i) > getIndent(input):
return true
-
+
+ def smallerIndent(input as OMetaInput, i):
+ return len(i) < getIndent(input)
+
def processDedent(input as OMetaInput, i):
+ original = input
indent = List(indentStack(input))
while cast(int, indent[-1]) > len(i):
indent.Pop()
- input = OMetaInput.Prepend(makeToken("dedent"), input)
+ input = OMetaInput.Prepend(makeToken("dedent"), input, original)
input = setIndentStack(input, indent)
assert sameIndent(input, i)
@@ -105,19 +146,39 @@ ometa WhitespaceSensitiveTokenizer():
def indentLevel(input as OMetaInput, indent as int, value as object):
return SuccessfulMatch(input.SetMemo("indentLevel", indent), value)
-
def processIndent(input as OMetaInput, i):
newStack = List(indentStack(input))
newStack.Push(len(i))
return SuccessfulMatch(setIndentStack(input, newStack), makeToken("indent"))
- def smallerIndent(input as OMetaInput, i):
- return len(i) < getIndent(input)
-
def getIndent(input as OMetaInput) as int:
return indentStack(input)[-1]
+ def getLine(input as OMetaInput) as int:
+ return input.GetMemo("line") or 1
+ def setLine(input as OMetaInput, value as int):
+ return input.SetMemo("line", value)
+
+ def setLineStart(input as OMetaInput, value as int):
+ return input.SetMemo("lineStart", value)
+
+ def newLine(input as OMetaInput):
+ input = setLineStart(input, input.Position)
+ return success(setLine(input, getLine(input) + 1))
+
+def setMemoStart(input as OMetaInput, value):
+ return SuccessfulMatch(input.SetMemo("start", value), null)
+
+def getMemoStart(input as OMetaInput):
+ return input.GetMemo("start")
+
+def getMemoEnd(input as OMetaInput):
+ return input.GetMemo("end")
+
+def getBack(value):
+ return value
+
def tokenMatches(token as Token, expected):
return expected is token.kind
@@ -125,12 +186,6 @@ def tokenValue(token as Token):
return null if token is null
return token.value
-def makeToken(kind):
- return Token(kind, kind)
-
-def makeToken(kind, value):
- return Token(kind, flatString(value))
-
def makeString(*values):
buffer = StringBuilder()
for value in values:
@@ -153,4 +208,13 @@ def flatString(buffer as StringBuilder, value):
buffer.Append(value)
otherwise:
for item in value:
- flatString buffer, item
+ flatString buffer, item
+
+def makeToken(kind):
+ return Token(kind, kind)
+
+def makeToken(kind, value):
+ return Token(kind, flatString(value))
+
+def makeToken(kind, value, start, end):
+ return Token(kind, flatString(value), start, end)
View
18 src/Boo.OMeta.Tests/Boo.OMeta.Tests.booproj
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ProjectGuid>{39203C2D-10BB-4FD5-8B84-241908614FFA}</ProjectGuid>
@@ -7,7 +7,7 @@
<OutputType>Library</OutputType>
<RootNamespace>Boo.OMeta.Tests</RootNamespace>
<AssemblyName>Boo.OMeta.Tests</AssemblyName>
- <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
+ <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<TargetFrameworkProfile />
<ProductVersion>10.0.0</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
@@ -64,9 +64,15 @@
</ItemGroup>
<Import Project="$(BooBinPath)\Boo.Microsoft.Build.targets" />
<ItemGroup>
- <Reference Include="nunit.framework, Version=2.4.8.0, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77" />
- <Reference Include="Boo.Lang, Version=2.0.9.5, Culture=neutral, PublicKeyToken=32c39770e9a21a67" />
- <Reference Include="Boo.Lang.Useful, Version=2.0.9.5, Culture=neutral, PublicKeyToken=32c39770e9a21a67" />
- <Reference Include="Boo.Lang.PatternMatching, Version=2.0.9.5, Culture=neutral, PublicKeyToken=32c39770e9a21a67" />
+ <Reference Include="Boo.Lang">
+ <HintPath>..\..\..\boo\build\Boo.Lang.dll</HintPath>
+ </Reference>
+ <Reference Include="Boo.Lang.PatternMatching">
+ <HintPath>..\..\..\boo\build\Boo.Lang.PatternMatching.dll</HintPath>
+ </Reference>
+ <Reference Include="Boo.Lang.Useful">
+ <HintPath>..\..\..\boo\build\Boo.Lang.Useful.dll</HintPath>
+ </Reference>
+ <Reference Include="nunit.framework" />
</ItemGroup>
</Project>
View
23 src/Boo.OMeta.Tests/OMetaInputTest.boo
@@ -11,12 +11,12 @@ class OMetaInputTest:
arg = "foo"
input = OMetaInput.Empty()
- input1 = OMetaInput.Prepend(arg, input)
- input2 = OMetaInput.Prepend(arg, input)
+ input1 = OMetaInput.Prepend(arg, input, null)
+ input2 = OMetaInput.Prepend(arg, input, null)
assert input1 == input2
- input3 = OMetaInput.Prepend("bar", input)
+ input3 = OMetaInput.Prepend("bar", input, null)
assert input1 != input3
# [Test]
@@ -44,4 +44,19 @@ class OMetaInputTest:
input = OMetaInput.For(range(3))
while not input.IsEmpty:
Assert.AreSame(input.Tail, input.Tail)
- input = input.Tail
+ input = input.Tail
+
+ [Test]
+ def OMetaInputWithMemoStoresValues():
+ input = OMetaInput.For(range(3))
+
+ input = input.SetMemo("a", 1)
+ input = input.Tail.SetMemo("b", 2)
+
+ assert input.GetMemo("a") == 1
+ assert input.GetMemo("b") == 2
+
+ assert input.Tail.GetMemo("a") == 1
+ assert input.Tail.GetMemo("b") == 2
+
+
View
4 src/Boo.OMeta.Tests/OMetaMacroTest.boo
@@ -64,10 +64,10 @@ class OMetaMacroTest:
def InputVariableIsAvailableToUserCode():
ometa InputTest:
foo = _ ^ (input.Position)
- bar = $(any(input)) and (input.Position == 1)
+ bar = $(any(input)) and (input.Position == 2)
tail = OMetaInput.For("01").Tail
- assertMatch 1, InputTest().foo(tail)
+ assertMatch 2, InputTest().foo(tail)
assertMatch char('1'), InputTest().bar(tail)
[Test]
View
4 src/Boo.OMeta/Boo.OMeta.booproj
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ProjectGuid>{EED6C932-8AEE-42CB-8837-C323DC74980B}</ProjectGuid>
@@ -7,7 +7,7 @@
<OutputType>Library</OutputType>
<RootNamespace>Boo.OMeta</RootNamespace>
<AssemblyName>Boo.OMeta</AssemblyName>
- <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
+ <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<SourceAnalysisOverrideSettingsFile>C:\Documents and Settings\rodrigob\Application Data\ICSharpCode/SharpDevelop3.0\Settings.SourceAnalysis</SourceAnalysisOverrideSettingsFile>
<NoStdLib>False</NoStdLib>
<Ducky>False</Ducky>
View
119 src/Boo.OMeta/OMetaInput.boo
@@ -2,6 +2,7 @@ namespace Boo.OMeta
import System
import System.Collections
+import System.Collections.Specialized
class OMetaInput:
@@ -9,25 +10,25 @@ class OMetaInput:
return ForEnumerator(enumerable.GetEnumerator())
static def ForEnumerator(enumerator as IEnumerator) as OMetaInput:
- return ForEnumerator(enumerator, 0)
+ return ForEnumerator(enumerator, 0, null)
- static def ForEnumerator(enumerator as IEnumerator, position as int) as OMetaInput:
+ static def ForEnumerator(enumerator as IEnumerator, position as int, prev as OMetaInput) as OMetaInput:
if enumerator.MoveNext():
- return EnumeratorInput(enumerator, position)
- return EndOfEnumeratorInput(position)
+ return EnumeratorInput(enumerator, position, prev)
+ return EndOfEnumeratorInput(position, prev)
- static def Prepend(argument, input as OMetaInput):
- return OMetaInputCons(argument, input)
+ static def Prepend(argument, input as OMetaInput, prev as OMetaInput):
+ return OMetaInputCons(argument, input, prev)
static def Singleton(o):
- return Prepend(o, Empty())
+ return Prepend(o, Empty(), null)
static def Empty():
return OMetaInput()
protected def constructor():
pass
-
+
virtual IsEmpty as bool:
get: return true
@@ -39,9 +40,12 @@ class OMetaInput:
virtual Position:
get: return int.MaxValue
-
+
+ virtual Prev as OMetaInput:
+ get: return null
+
virtual def SetMemo(key as string, value) as OMetaInput:
- return OMetaInputWithMemo(key, value, self)
+ return OMetaInputWithMemo(key, value, self, Prev)
virtual def GetMemo(key as string):
return null
@@ -68,6 +72,9 @@ internal class DelegatingInput(OMetaInput):
override Position:
get: return _input.Position
+ override Prev:
+ get: return _input.Prev
+
override def SetMemo(key as string, value):
return _input.SetMemo(key, value)
@@ -78,54 +85,80 @@ internal class DelegatingInput(OMetaInput):
return _input.ToString()
internal class OMetaInputWithMemo(DelegatingInput):
-
- final _key as string
- final _value as object
+ final _dictionary as ListDictionary
_tail as OMetaInput
+ final _prev as OMetaInput
- def constructor(key as string, value, input as OMetaInput):
+ def constructor(key as string, value, input as OMetaInput, prev):
super(input)
- _key = key
- _value = value
+ _dictionary = ListDictionary()
+ _dictionary.Add(key, value)
+ _prev = prev
+ protected def constructor(input as OMetaInput, prev, dictionary as ListDictionary):
+ super(input)
+ _dictionary = dictionary
+ _prev = prev
+
+ protected def Clone():
+ dictionaryCopy = ListDictionary()
+ for item as DictionaryEntry in _dictionary: dictionaryCopy.Add(item.Key, item.Value)
+ return OMetaInputWithMemo(_input, _prev, dictionaryCopy)
+
+ protected def SetDictionaryEntry(key as string, value):
+ _dictionary[key] = value
+
override Tail:
- get: return _tail or _tail = OMetaInputMemoTail(self, _input.Tail)
+ get: return _tail or _tail = OMetaInputMemoTail(self, _input.Tail, self)
+
+ override Prev:
+ get: return _prev
override def SetMemo(key as string, value) as OMetaInput:
- if key is _key:
- return OMetaInputWithMemo(key, value, _input)
- else:
- return OMetaInputWithMemo(key, value, self)
-
+ newInputWithMemo = Clone()
+ newInputWithMemo.SetDictionaryEntry(key, value)
+ return newInputWithMemo
+
override def GetMemo(key as string):
- if key is _key: return _value
- return super(key)
+ if _dictionary.Contains(key): return _dictionary[key]
+ return _input.GetMemo(key)
internal class OMetaInputMemoTail(DelegatingInput):
- final _parent as OMetaInput
+ final _parent as OMetaInputWithMemo
_tail as OMetaInput
+ final _prev as OMetaInput
- def constructor(parent as OMetaInput, input as OMetaInput):
+ def constructor(parent as OMetaInputWithMemo, input as OMetaInput, prev as OMetaInput):
super(input)
_parent = parent
+ _prev = prev
+ override Prev:
+ get: return _prev
+
override Tail:
- get: return _tail or _tail = OMetaInputMemoTail(self, _input.Tail)
+ get: return _tail or _tail = OMetaInputMemoTail(_parent, _input.Tail, self)
+
override def SetMemo(key as string, value) as OMetaInput:
- return _parent.SetMemo(key, value).Tail
+ return OMetaInputMemoTail(_parent.SetMemo(key, value), _input, _prev)
override def GetMemo(key as string):
return _parent.GetMemo(key)
internal class OMetaInputCons(OMetaInput):
- [getter(Head)] _argument as object
+ [getter(Head)] _head as object
[getter(Tail)] _tail as OMetaInput
+ final _prev as OMetaInput
- def constructor(argument, tail as OMetaInput):
- _argument = argument
+ def constructor(head, tail as OMetaInput, prev as OMetaInput):
+ _head = head
_tail = tail
+ _prev = prev
+ override Prev:
+ get: return _prev
+
override IsEmpty:
get: return false
@@ -134,12 +167,14 @@ internal class EnumeratorInput(OMetaInput):
final _position as int
final _input as IEnumerator
final _head as object
+ final _prev as OMetaInput
_tail as OMetaInput
- internal def constructor(input as IEnumerator, position as int):
+ internal def constructor(input as IEnumerator, position as int, prev as OMetaInput):
_input = input
_head = input.Current
_position = position
+ _prev = prev
override Position:
get: return _position
@@ -151,15 +186,25 @@ internal class EnumeratorInput(OMetaInput):
get: return _head
override Tail:
- get: return _tail or _tail = ForEnumerator(_input, _position + 1)
+ get: return _tail or _tail = ForEnumerator(_input, _position + 1, self)
+
+ override Prev:
+ get: return _prev
override def ToString():
return "OMetaInput(Head: ${Head}, Position: ${Position})"
-internal class EndOfEnumeratorInput(OMetaInput):
-
- def constructor(position as int):
- _position = position
+
+internal class EndOfEnumeratorInput(OMetaInput):
+ final _prev as OMetaInput
+
+ def constructor(position as int, prev as OMetaInput):
+ _position = position
+ _prev = prev
+
+ override Prev:
+ get: return _prev
+
[getter(Position)]
_position as int
View
6 src/Boo.OMeta/OMetaMacroProcessor.boo
@@ -36,6 +36,7 @@ class OMetaMacroProcessor:
case ExpressionStatement(Expression: [| $(ReferenceExpression(Name: name)) = $pattern |]):
m0 = [|
private def $("${name}_rule")(context as OMetaEvaluationContext, input_ as OMetaInput) as OMetaMatch:
+ lastMatch as OMetaMatch = SuccessfulMatch(input_, null)
$(OMetaMacroRuleProcessor(name, options, ruleNames).expand(pattern))
|]
type.Members.Add(m0)
@@ -53,17 +54,18 @@ class OMetaMacroProcessor:
case ExpressionStatement(Expression: [| $(ReferenceExpression(Name: name))[$arg] = $pattern |]):
m0 = [|
private def $("${name}_rule")(context as OMetaEvaluationContext, input_ as OMetaInput) as OMetaMatch:
+ lastMatch as OMetaMatch = SuccessfulMatch(input_, null)
$(OMetaMacroRuleProcessor(name, options, ruleNames).expand(pattern, arg))
|]
type.Members.Add(m0)
m1 = [|
def $name(input as OMetaInput, $arg):
- return Apply($name, OMetaInput.Prepend($arg, input))
+ return Apply($name, OMetaInput.Prepend($arg, input, null))
|]
type.Members.Add(m1)
m2 = [|
def $name(input as System.Collections.IEnumerable, $arg):
- return Apply($name, OMetaInput.Prepend($arg, OMetaInput.For(input)))
+ return Apply($name, OMetaInput.Prepend($arg, OMetaInput.For(input), null))
|]
type.Members.Add(m2)
View
15 src/Boo.OMeta/OMetaMacroRuleProcessor.boo
@@ -171,22 +171,23 @@ class OMetaMacroRuleProcessor:
return e
def expand(block as Block, e as Expression, input as Expression, lastMatch as ReferenceExpression):
+ lm as Expression = [| $lastMatch.Input |]
+
match e:
- case SpliceExpression(Expression: rule):
- block.Add([| $lastMatch = $(processVariables(rule, input)) |])
-
+ case SpliceExpression(Expression: rule):
+ block.Add([| $lastMatch = $(processVariables(rule, lm)) |])
case [| $rule[$arg] |]:
newInput = uniqueName()
effectiveArg = effectiveArgForRule(arg)
- block.Add([| $newInput = OMetaInput.Prepend($effectiveArg, $input) |])
+ block.Add([| $newInput = OMetaInput.Prepend($effectiveArg, $input, null) |])
expand block, rule, newInput, lastMatch
case [| $pattern and $predicate |]:
oldInput = uniqueName()
block.Add([| $oldInput = $input |])
- expand block, pattern, input, lastMatch
+ expand block, pattern, input, lastMatch
checkPredicate = [|
- if $lastMatch isa SuccessfulMatch and not $(processVariables(predicate, input)):
+ if $lastMatch isa SuccessfulMatch and not $(processVariables(predicate, lm)):
$lastMatch = FailedMatch($oldInput, PredicateFailure($(predicate.ToCodeString())))
|]
block.Add(checkPredicate)
@@ -198,7 +199,7 @@ class OMetaMacroRuleProcessor:
block:
smatch = $lastMatch as SuccessfulMatch
if smatch is not null:
- $lastMatch = SuccessfulMatch(smatch.Input, $(processVariables(value, input)))
+ $lastMatch = SuccessfulMatch(smatch.Input, $(processVariables(value, lm)))
|].Body
block.Add(code)
View
2  src/Boo.OMeta/TokensMacro.boo
@@ -29,7 +29,7 @@ it generates:
for stmt in tokens.Body.Statements:
match stmt:
case ExpressionStatement(Expression: [| $name = $pattern |]):
- e = [| $name = $pattern >> value ^ makeToken($(name.ToString()), value) |]
+ e = [| $name = (("" ^ makeToken("here", null, input, null)) >> start, $pattern >> value) ^ makeToken($(name.ToString()), value, (start as Token).start, null) |]
e.LexicalInfo = stmt.LexicalInfo
block.Add(e)
View
3  src/OMetaParserConsole/OMetaParserConsole.booproj
@@ -66,8 +66,5 @@
<Name>Boo.OMeta</Name>
</ProjectReference>
</ItemGroup>
- <ItemGroup>
- <None Include="app.config" />
- </ItemGroup>
<Import Project="$(BooBinPath)\Boo.Microsoft.Build.targets" />
</Project>
Something went wrong with that request. Please try again.