summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdrian Thurston <thurston@complang.org>2015-01-23 17:01:07 -0500
committerAdrian Thurston <thurston@complang.org>2015-01-23 17:01:07 -0500
commit72a8d8a9dd19453db5764a8c11e8f5e1c5a4f351 (patch)
tree45f1f8142fdfe36ef19013f2d0a6d8227717545d
parent92da67efa0e2d0f6c7858bd35d4e1bbad61d1e3b (diff)
downloadcolm-72a8d8a9dd19453db5764a8c11e8f5e1c5a4f351.tar.gz
revert "moved away the larger grammars for known langs"
This reverts commit 04a32202c1aae4a1c69539ce7dd21dff3a93c7fb.
-rw-r--r--test/binary1.lm1938
-rw-r--r--test/generate1.lm773
-rw-r--r--test/generate2.lm223
-rw-r--r--test/lookup1.lm2594
4 files changed, 5528 insertions, 0 deletions
diff --git a/test/binary1.lm b/test/binary1.lm
new file mode 100644
index 00000000..d84790c6
--- /dev/null
+++ b/test/binary1.lm
@@ -0,0 +1,1938 @@
+
+context binary
+
+# Used for most of the grammar.
+token octet /any/
+
+# Filled in during the parsing of resource records. Determine what RR_UNKNOWN
+# translates to.
+rr_type_value: int
+rr_class_value: int
+
+# Tokens generated from RR_UNKNOWN. Used to pick the kind
+# of resource record to attempt to parse.
+token RR_A // # 1 a host address
+token RR_NS // # 2 an authoritative name server
+token RR_MD // # 3 a mail destination (Obsolete - use MX)
+token RR_MF // # 4 a mail forwarder (Obsolete - use MX)
+token RR_CNAME // # 5 the canonical name for an alias
+token RR_SOA // # 6 marks the start of a zone of authority
+token RR_MB // # 7 a mailbox domain name (EXPERIMENTAL)
+token RR_MG // # 8 a mail group member (EXPERIMENTAL)
+token RR_MR // # 9 a mail rename domain name (EXPERIMENTAL)
+token RR_NULL // # 10 a null RR (EXPERIMENTAL)
+token RR_WKS // # 11 a well known service description
+token RR_PTR // # 12 a domain name pointer
+token RR_HINFO // # 13 host information
+token RR_MINFO // # 14 mailbox or mail list information
+token RR_MX // # 15 mail exchange
+token RR_TXT // # 16 text strings
+
+token RR_UNKNOWN
+ /''/
+ {
+ id: int = typeid<RR_UNKNOWN>
+ if rr_type_value == 1
+ id = typeid<RR_A>
+ elsif rr_type_value == 2
+ id = typeid<RR_NS>
+ elsif rr_type_value == 5
+ id = typeid<RR_CNAME>
+ elsif rr_type_value == 12
+ id = typeid<RR_PTR>
+ elsif rr_type_value == 15
+ id = typeid<RR_MX>
+ elsif rr_type_value == 16
+ id = typeid<RR_TXT>
+
+ input->push( make_token( id '' ) )
+ }
+
+# Convert two octets in network order into an unsigned 16 bit value.
+int network_uord16( o1: octet o2: octet )
+{
+ return o1.data.uord8() * 256 + o2.data.uord8()
+}
+
+
+def message
+ [header questions answers authorities additionals]
+
+question_count: int
+answer_count: int
+authority_count: int
+additional_count: int
+
+# Message Header
+#
+# 1 1 1 1 1 1
+# 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+# | ID |
+# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+# |QR| Opcode |AA|TC|RD|RA| Z | RCODE |
+# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+# | QDCOUNT |
+# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+# | ANCOUNT |
+# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+# | NSCOUNT |
+# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+# | ARCOUNT |
+# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+def header
+ [header_id header_fields count count count count]
+ {
+ question_count = r3.count
+ answer_count = r4.count
+ authority_count = r5.count
+ additional_count = r6.count
+ }
+
+def header_id
+ [octet octet]
+
+def header_fields
+ [octet octet]
+
+def count
+ count: int
+ [octet octet]
+ {
+ lhs.count = network_uord16( r1 r2 )
+ }
+
+#
+# Counting Primitives
+#
+# Uses a stack of lengths. Using a stack allows for counted lists to be
+# nested. As the list is consumed it brings the count down to zero. To use
+# it, push a new count value to the list and include it in a
+# right-recursive list like so:
+#
+# def LIST
+# [count_inc ITEM LIST]
+# [count_end]
+# end
+#
+
+struct int_el
+ Int: int
+
+ list_el el
+end
+
+CL: list<int_el>
+
+int start_list( count: int )
+{
+ IntEl: int_el = new int_el
+ IntEl->Int = count
+ CL->push( IntEl )
+}
+
+def count_inc
+ []
+ {
+ if top( CL ) == 0 {
+ reject
+ } else {
+ Int: int = pop( CL )
+ Int = Int - 1
+ push( CL Int )
+ }
+ }
+
+def count_end
+ []
+ {
+ if top( CL ) != 0 {
+ reject
+ } else {
+ CL->pop()
+ }
+ }
+
+#
+# Octet List
+#
+
+# General octet list. Length must be set to use this.
+def octet_list
+ [count_inc octet octet_list]
+| [count_end]
+
+
+#
+# Names
+#
+
+def name
+ [name_part* name_end]
+
+# Name part lists are terminated by a zero length or a pointer.
+def name_end
+ # Zero length ending
+ [octet]
+ {
+ val: int = r1.data.uord8()
+ if val != 0 {
+ reject
+ }
+ }
+
+ # Pointer ending
+ # +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ # | 1 1| OFFSET |
+ # +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+| [octet octet]
+ {
+ val: int = r1.data.uord8()
+ if val < 64 {
+ reject
+ }
+ }
+
+#
+# Get some number of bytes.
+#
+
+# How many to get
+nbytes: int
+
+# We use this token to eliminate the lookahead that would be needed to
+# cause a reduce of part_len. This forces whatever comes before nbytes to
+# be reduced before nbytes_data token is fetched from the scanner. We need
+# this because nbytes_data depends on the nbytes in the context and we need
+# to ensure that it is set.
+token nb_empty /''/
+
+# Fetch nbytes bytes.
+token nbytes_data
+ /''/
+ {
+ input->push( make_token( typeid<nbytes_data> input->pull(nbytes) ) )
+ }
+
+def nbytes
+ [nb_empty nbytes_data]
+
+def name_part
+ [part_len nbytes]
+
+
+def part_len
+ [octet]
+ {
+ # A name part list is terminated either by a zero length or a pointer,
+ # which must have the two high bits set.
+ count: int = r1.data.uord8()
+ if count == 0 || count >= 64 {
+ reject
+ } else {
+ # Set the number of bytes to get for the name part.
+ nbytes = count
+ }
+ }
+
+#
+# Resource Records
+#
+
+# 1 1 1 1 1 1
+# 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+# | |
+# / /
+# / NAME /
+# | |
+# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+# | TYPE |
+# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+# | CLASS |
+# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+# | TTL |
+# | |
+# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+# | RDLENGTH |
+# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--|
+# / RDATA /
+# / /
+# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+def resource_record
+ [name rr_type rr_class ttl rdlength rdata]
+
+def rr_type
+ [octet octet]
+ {
+ rr_type_value = network_uord16( r1 r2 )
+ }
+
+def rr_class
+ value: int
+ [octet octet]
+ {
+ rr_class_value = network_uord16( r1 r2 )
+ }
+
+def ttl
+ [octet octet octet octet]
+
+token rdata_bytes
+ /''/
+ {
+ input->push( make_token( typeid<rdata_bytes> input->pull(rdata_length) ) )
+ }
+
+def rdlength
+ [octet octet]
+ {
+ rdata_length = network_uord16( r1 r2 )
+ }
+
+rdata_length: int
+
+def rdata
+ [RR_UNKNOWN rdata_bytes]
+| [RR_A address]
+| [RR_NS name]
+| [RR_CNAME name]
+| [RR_PTR name]
+| [RR_MX octet octet name]
+| [RR_TXT rdata_bytes]
+
+
+#
+# Address
+#
+def address [octet octet octet octet]
+
+#
+# List of Questions
+#
+
+def questions
+ [load_question_count question_list]
+
+def load_question_count
+ []
+ {
+ start_list( question_count )
+ }
+
+def question_list
+ [count_inc question question_list]
+| [count_end]
+
+#
+# Question
+#
+
+# 1 1 1 1 1 1
+# 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+# | |
+# / QNAME /
+# / /
+# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+# | QTYPE |
+# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+# | QCLASS |
+# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+def question
+ [name qtype qclass]
+
+def qtype
+ [octet octet]
+
+def qclass
+ [octet octet]
+
+#
+# List of Answers
+#
+
+def answers
+ [load_answer_count answer_list]
+
+def load_answer_count
+ []
+ {
+ start_list( answer_count )
+ }
+
+def answer_list
+ [count_inc answer answer_list]
+| [count_end]
+
+#
+# Answer
+#
+
+def answer
+ [resource_record]
+
+#
+# List of Authorities
+#
+
+def authorities
+ [load_authority_count authority_list]
+
+def load_authority_count
+ []
+ {
+ start_list( authority_count )
+ }
+
+def authority_list
+ [count_inc authority authority_list]
+| [count_end]
+
+#
+# Authority
+#
+
+def authority
+ [resource_record]
+
+#
+# List of Additionals
+#
+
+def additionals
+ [load_additional_count additional_list]
+
+def load_additional_count
+ []
+ {
+ start_list( additional_count )
+ }
+
+def additional_list
+ [count_inc additional additional_list]
+| [count_end]
+
+#
+# Additional
+#
+
+def additional
+ [resource_record]
+
+
+def start
+ [message*]
+
+#
+# Grammar End.
+#
+
+int print_RR_UNKNOWN( s: start )
+{
+ for I:rdata in s {
+ if match I [u:RR_UNKNOWN rdata_bytes] {
+ print( 'UNKNOWN TYPE\n' )
+ }
+ }
+}
+
+int print_RR_A( s: start )
+{
+ for I:rdata in s {
+ if match I [RR_A o1:octet o2:octet o3:octet o4:octet] {
+ print( 'RR_A: ' o1.data.uord8() '.' o2.data.uord8() '.'
+ o3.data.uord8() '.' o4.data.uord8() '\n' )
+ }
+ }
+}
+
+struct name_map_el
+ Name: name
+ map_el<int> el
+end
+
+int print_name( n: name m: map<int name_map_el> )
+{
+ for P: name_part in n {
+ match P [part_len D:nbytes]
+ print( D '.' )
+ }
+
+ for E:name_end in n {
+ if match E [o1:octet o2:octet] {
+ val: int = (o1.data.uord8() - 192) * 256 + o2.data.uord8()
+ print( '[' val ']' )
+ nameInMap: name_map_el = m->find( val )
+ print_name( nameInMap->Name m )
+ }
+ }
+}
+
+int print_all_names( s: start )
+{
+ for M: message in s {
+ m: map<int name_map_el> = new map<int name_map_el>
+
+ O: octet = octet in M
+
+ for N: name in M {
+ match N [name_part* E:name_end]
+
+ for NP: name_part* in N {
+ if match NP [L: octet nbytes name_part*] {
+ messageOffset: int = L.pos - O.pos
+ construct n: name [NP E]
+ El: name_map_el = new name_map_el
+ El->key = messageOffset
+ El->Name = n
+ m->insert( El )
+ }
+ }
+ }
+
+ for I: name in M {
+ print_name( I m )
+ print( '\n' )
+ }
+ }
+}
+
+end # binary
+
+Binary: binary = new binary
+Binary->CL = new list<binary::int_el>
+
+int top( L: list<binary::int_el> )
+{
+ Top: binary::int_el = L->top
+ return Top->Int
+}
+
+int pop( L: list<binary::int_el> )
+{
+ Top: binary::int_el = L->pop()
+ return Top->Int
+}
+
+int push( L: list<binary::int_el> Int: int )
+{
+ Top: binary::int_el = new binary::int_el
+ Top->Int = Int
+ L->push( Top )
+}
+
+parse S: binary::start(Binary) [ stdin ]
+print_all_names( S )
+print( '*** SUCCESS ***\n' )
+##### EXP #####
+www.google.ca.
+www.google.ca.
+[12]www.google.ca.
+www.google.com.
+[43]www.google.com.
+www.l.[47]google.com.
+[71]www.l.[47]google.com.
+[75]l.[47]google.com.
+a.[75]l.[47]google.com.
+[75]l.[47]google.com.
+d.[75]l.[47]google.com.
+[75]l.[47]google.com.
+e.[75]l.[47]google.com.
+[75]l.[47]google.com.
+f.[75]l.[47]google.com.
+[75]l.[47]google.com.
+g.[75]l.[47]google.com.
+[75]l.[47]google.com.
+b.[75]l.[47]google.com.
+[107]a.[75]l.[47]google.com.
+[123]d.[75]l.[47]google.com.
+[139]e.[75]l.[47]google.com.
+[155]f.[75]l.[47]google.com.
+[171]g.[75]l.[47]google.com.
+[187]b.[75]l.[47]google.com.
+clients1.google.ca.
+clients1.google.ca.
+[12]clients1.google.ca.
+clients.l.google.com.
+[48]clients.l.google.com.
+[56]l.google.com.
+e.[56]l.google.com.
+[56]l.google.com.
+f.[56]l.google.com.
+[56]l.google.com.
+g.[56]l.google.com.
+[56]l.google.com.
+b.[56]l.google.com.
+[56]l.google.com.
+a.[56]l.google.com.
+[56]l.google.com.
+d.[56]l.google.com.
+[98]e.[56]l.google.com.
+[114]f.[56]l.google.com.
+[130]g.[56]l.google.com.
+[146]b.[56]l.google.com.
+[162]a.[56]l.google.com.
+[178]d.[56]l.google.com.
+en-us.fxfeeds.mozilla.com.
+en-us.fxfeeds.mozilla.com.
+[12]en-us.fxfeeds.mozilla.com.
+fxfeeds.mozilla.org.
+[55]fxfeeds.mozilla.org.
+[63]mozilla.org.
+ns1.[63]mozilla.org.
+[63]mozilla.org.
+ns2.[63]mozilla.org.
+[63]mozilla.org.
+ns3.[63]mozilla.org.
+[104]ns1.[63]mozilla.org.
+[122]ns2.[63]mozilla.org.
+[140]ns3.[63]mozilla.org.
+fxfeeds.mozilla.com.
+fxfeeds.mozilla.com.
+[12]fxfeeds.mozilla.com.
+fxfeeds.mozilla.org.
+[49]fxfeeds.mozilla.org.
+[57]mozilla.org.
+ns2.[57]mozilla.org.
+[57]mozilla.org.
+ns3.[57]mozilla.org.
+[57]mozilla.org.
+ns1.[57]mozilla.org.
+[98]ns2.[57]mozilla.org.
+[116]ns3.[57]mozilla.org.
+[134]ns1.[57]mozilla.org.
+newsrss.bbc.co.uk.
+newsrss.bbc.co.uk.
+[12]newsrss.bbc.co.uk.
+newsrss.bbc.net.uk.
+[47]newsrss.bbc.net.uk.
+[55]bbc.net.uk.
+ns0.thdo.bbc.co.[63]uk.
+[55]bbc.net.uk.
+ns0.rbsov.[104]bbc.co.[63]uk.
+[95]ns0.thdo.bbc.co.[63]uk.
+[125]ns0.rbsov.[104]bbc.co.[63]uk.
+news.google.ca.
+news.google.ca.
+[12]news.google.ca.
+news.google.com.
+[44]news.google.com.
+news.l.[49]google.com.
+[73]news.l.[49]google.com.
+[78]l.[49]google.com.
+d.[78]l.[49]google.com.
+[78]l.[49]google.com.
+e.[78]l.[49]google.com.
+[78]l.[49]google.com.
+f.[78]l.[49]google.com.
+[78]l.[49]google.com.
+g.[78]l.[49]google.com.
+[78]l.[49]google.com.
+b.[78]l.[49]google.com.
+[78]l.[49]google.com.
+a.[78]l.[49]google.com.
+[110]d.[78]l.[49]google.com.
+[126]e.[78]l.[49]google.com.
+[142]f.[78]l.[49]google.com.
+[158]g.[78]l.[49]google.com.
+[174]b.[78]l.[49]google.com.
+[190]a.[78]l.[49]google.com.
+nt3.ggpht.com.
+nt3.ggpht.com.
+[12]nt3.ggpht.com.
+news.l.google.com.
+[43]news.l.google.com.
+[48]l.google.com.
+f.[48]l.google.com.
+[48]l.google.com.
+g.[48]l.google.com.
+[48]l.google.com.
+b.[48]l.google.com.
+[48]l.google.com.
+a.[48]l.google.com.
+[48]l.google.com.
+d.[48]l.google.com.
+[48]l.google.com.
+e.[48]l.google.com.
+[90]f.[48]l.google.com.
+[106]g.[48]l.google.com.
+[122]b.[48]l.google.com.
+[138]a.[48]l.google.com.
+[154]d.[48]l.google.com.
+[170]e.[48]l.google.com.
+csi.gstatic.com.
+csi.gstatic.com.
+[12]csi.gstatic.com.
+csi.l.google.com.
+[45]csi.l.google.com.
+[49]l.google.com.
+d.[49]l.google.com.
+[49]l.google.com.
+e.[49]l.google.com.
+[49]l.google.com.
+f.[49]l.google.com.
+[49]l.google.com.
+g.[49]l.google.com.
+[49]l.google.com.
+b.[49]l.google.com.
+[49]l.google.com.
+a.[49]l.google.com.
+[91]d.[49]l.google.com.
+[107]e.[49]l.google.com.
+[123]f.[49]l.google.com.
+[139]g.[49]l.google.com.
+[155]b.[49]l.google.com.
+[171]a.[49]l.google.com.
+www.nytimes.com.
+www.nytimes.com.
+[12]www.nytimes.com.
+nytimes.com.
+nydns1.about.[57]com.
+[49]nytimes.com.
+ns1t.[49]nytimes.com.
+[49]nytimes.com.
+nydns2.[79]about.[57]com.
+[72]nydns1.about.[57]com.
+[99]ns1t.[49]nytimes.com.
+[118]nydns2.[79]about.[57]com.
+graphics8.nytimes.com.
+graphics8.nytimes.com.
+[12]graphics8.nytimes.com.
+graphics478.nytimes.com.edgesuite.net.
+[51]graphics478.nytimes.com.edgesuite.net.
+a1116.x.akamai.[85]net.
+[102]a1116.x.akamai.[85]net.
+[102]a1116.x.akamai.[85]net.
+[108]x.akamai.[85]net.
+n0x.[110]akamai.[85]net.
+[108]x.akamai.[85]net.
+n1x.[110]akamai.[85]net.
+[108]x.akamai.[85]net.
+n6x.[110]akamai.[85]net.
+[108]x.akamai.[85]net.
+n3x.[110]akamai.[85]net.
+[108]x.akamai.[85]net.
+n2x.[110]akamai.[85]net.
+[108]x.akamai.[85]net.
+n7x.[110]akamai.[85]net.
+[108]x.akamai.[85]net.
+n5x.[110]akamai.[85]net.
+[108]x.akamai.[85]net.
+n8x.[110]akamai.[85]net.
+[108]x.akamai.[85]net.
+n4x.[110]akamai.[85]net.
+[163]n0x.[110]akamai.[85]net.
+[181]n1x.[110]akamai.[85]net.
+[199]n6x.[110]akamai.[85]net.
+[217]n3x.[110]akamai.[85]net.
+[235]n2x.[110]akamai.[85]net.
+[253]n7x.[110]akamai.[85]net.
+[271]n5x.[110]akamai.[85]net.
+[289]n8x.[110]akamai.[85]net.
+[307]n4x.[110]akamai.[85]net.
+timespeople.nytimes.com.
+timespeople.nytimes.com.
+[12]timespeople.nytimes.com.
+nytimes.com.
+nydns2.about.[65]com.
+[57]nytimes.com.
+nydns1.[87]about.[65]com.
+[57]nytimes.com.
+ns1t.[57]nytimes.com.
+[80]nydns2.about.[65]com.
+[107]nydns1.[87]about.[65]com.
+[128]ns1t.[57]nytimes.com.
+googleads.g.doubleclick.net.
+googleads.g.doubleclick.net.
+[12]googleads.g.doubleclick.net.
+pagead.l.doubleclick.net.
+[57]pagead.l.doubleclick.net.
+[64]l.doubleclick.net.
+b.l.google.com.
+[64]l.doubleclick.net.
+d.[113]l.google.com.
+[64]l.doubleclick.net.
+e.[113]l.google.com.
+[64]l.doubleclick.net.
+f.[113]l.google.com.
+[64]l.doubleclick.net.
+g.[113]l.google.com.
+[64]l.doubleclick.net.
+a.[113]l.google.com.
+[111]b.l.google.com.
+[139]d.[113]l.google.com.
+[155]e.[113]l.google.com.
+[171]f.[113]l.google.com.
+[187]g.[113]l.google.com.
+[203]a.[113]l.google.com.
+up.nytimes.com.
+up.nytimes.com.
+[12]up.nytimes.com.
+up.about.akadns.net.
+[44]up.about.akadns.net.
+[53]akadns.net.
+eur1.[53]akadns.net.
+[53]akadns.net.
+use3.[53]akadns.net.
+[53]akadns.net.
+use4.[53]akadns.net.
+[53]akadns.net.
+usw2.[53]akadns.net.
+[53]akadns.net.
+za.akadns.org.
+[53]akadns.net.
+zb.[172]akadns.org.
+[53]akadns.net.
+zc.[172]akadns.org.
+[53]akadns.net.
+zd.[172]akadns.org.
+[53]akadns.net.
+asia9.[53]akadns.net.
+[93]eur1.[53]akadns.net.
+[112]use3.[53]akadns.net.
+[131]use4.[53]akadns.net.
+[150]usw2.[53]akadns.net.
+[169]za.akadns.org.
+[196]zb.[172]akadns.org.
+[213]zc.[172]akadns.org.
+[230]zd.[172]akadns.org.
+[247]asia9.[53]akadns.net.
+pix04.revsci.net.
+pix04.revsci.net.
+[12]pix04.revsci.net.
+revsci.net.
+ns2.p16.dynect.[57]net.
+[50]revsci.net.
+ns3.[76]p16.dynect.[57]net.
+[50]revsci.net.
+ns1.[76]p16.dynect.[57]net.
+[50]revsci.net.
+ns4.[76]p16.dynect.[57]net.
+[72]ns2.p16.dynect.[57]net.
+[101]ns3.[76]p16.dynect.[57]net.
+[119]ns1.[76]p16.dynect.[57]net.
+[137]ns4.[76]p16.dynect.[57]net.
+wt.o.nytimes.com.
+wt.o.nytimes.com.
+[12]wt.o.nytimes.com.
+nytimes.webtrends.akadns.net.
+[46]nytimes.webtrends.akadns.net.
+[64]akadns.net.
+use3.[64]akadns.net.
+[64]akadns.net.
+use4.[64]akadns.net.
+[64]akadns.net.
+usw2.[64]akadns.net.
+[64]akadns.net.
+za.akadns.org.
+[64]akadns.net.
+zb.[164]akadns.org.
+[64]akadns.net.
+zc.[164]akadns.org.
+[64]akadns.net.
+zd.[164]akadns.org.
+[64]akadns.net.
+asia9.[64]akadns.net.
+[64]akadns.net.
+eur1.[64]akadns.net.
+[104]use3.[64]akadns.net.
+[123]use4.[64]akadns.net.
+[142]usw2.[64]akadns.net.
+[161]za.akadns.org.
+[188]zb.[164]akadns.org.
+[205]zc.[164]akadns.org.
+[222]zd.[164]akadns.org.
+[239]asia9.[64]akadns.net.
+[259]eur1.[64]akadns.net.
+te.nytimes.com.
+ar.voicefive.com.
+te.nytimes.com.
+[12]te.nytimes.com.
+nytd.te.tacoda.net.
+[44]nytd.te.tacoda.net.
+te.tacoda.akadns.[59]net.
+[76]te.tacoda.akadns.[59]net.
+[86]akadns.[59]net.
+use4.[86]akadns.[59]net.
+[86]akadns.[59]net.
+usw2.[86]akadns.[59]net.
+[86]akadns.[59]net.
+za.akadns.org.
+[86]akadns.[59]net.
+zb.[164]akadns.org.
+[86]akadns.[59]net.
+zc.[164]akadns.org.
+[86]akadns.[59]net.
+zd.[164]akadns.org.
+[86]akadns.[59]net.
+asia9.[86]akadns.[59]net.
+[86]akadns.[59]net.
+eur1.[86]akadns.[59]net.
+[86]akadns.[59]net.
+use3.[86]akadns.[59]net.
+[123]use4.[86]akadns.[59]net.
+[142]usw2.[86]akadns.[59]net.
+[161]za.akadns.org.
+[188]zb.[164]akadns.org.
+[205]zc.[164]akadns.org.
+[222]zd.[164]akadns.org.
+[239]asia9.[86]akadns.[59]net.
+[259]eur1.[86]akadns.[59]net.
+[278]use3.[86]akadns.[59]net.
+ar.voicefive.com.
+[12]ar.voicefive.com.
+ar.gta.voicefive.com.
+[46]ar.gta.voicefive.com.
+[49]gta.voicefive.com.
+gta02.ord.[53]voicefive.com.
+[49]gta.voicefive.com.
+gta01.iad.[53]voicefive.com.
+[49]gta.voicefive.com.
+gta01.[102]ord.[53]voicefive.com.
+[49]gta.voicefive.com.
+gta02.[126]iad.[53]voicefive.com.
+[96]gta02.ord.[53]voicefive.com.
+[120]gta01.iad.[53]voicefive.com.
+[144]gta01.[102]ord.[53]voicefive.com.
+[164]gta02.[126]iad.[53]voicefive.com.
+www.google.com.
+www.google.com.
+[12]www.google.com.
+www.l.google.com.
+[44]www.l.google.com.
+[48]l.google.com.
+d.[48]l.google.com.
+[48]l.google.com.
+e.[48]l.google.com.
+[48]l.google.com.
+f.[48]l.google.com.
+[48]l.google.com.
+g.[48]l.google.com.
+[48]l.google.com.
+b.[48]l.google.com.
+[48]l.google.com.
+a.[48]l.google.com.
+[90]d.[48]l.google.com.
+[106]e.[48]l.google.com.
+[122]f.[48]l.google.com.
+[138]g.[48]l.google.com.
+[154]b.[48]l.google.com.
+[170]a.[48]l.google.com.
+www.google-analytics.com.
+www.google-analytics.com.
+[12]www.google-analytics.com.
+www-google-analytics.l.google.com.
+[54]www-google-analytics.l.google.com.
+[75]l.google.com.
+f.[75]l.google.com.
+[75]l.google.com.
+g.[75]l.google.com.
+[75]l.google.com.
+b.[75]l.google.com.
+[75]l.google.com.
+a.[75]l.google.com.
+[75]l.google.com.
+d.[75]l.google.com.
+[75]l.google.com.
+e.[75]l.google.com.
+[117]f.[75]l.google.com.
+[133]g.[75]l.google.com.
+[149]b.[75]l.google.com.
+[165]a.[75]l.google.com.
+[181]d.[75]l.google.com.
+[197]e.[75]l.google.com.
+pagead2.googlesyndication.com.
+pagead2.googlesyndication.com.
+[12]pagead2.googlesyndication.com.
+pagead.l.google.com.
+[59]pagead.l.google.com.
+[66]l.google.com.
+g.[66]l.google.com.
+[66]l.google.com.
+b.[66]l.google.com.
+[66]l.google.com.
+a.[66]l.google.com.
+[66]l.google.com.
+d.[66]l.google.com.
+[66]l.google.com.
+e.[66]l.google.com.
+[66]l.google.com.
+f.[66]l.google.com.
+[108]g.[66]l.google.com.
+[124]b.[66]l.google.com.
+[140]a.[66]l.google.com.
+[156]d.[66]l.google.com.
+[172]e.[66]l.google.com.
+[188]f.[66]l.google.com.
+maps.google.com.
+maps.google.com.
+[12]maps.google.com.
+maps.l.google.com.
+[45]maps.l.google.com.
+[50]l.google.com.
+b.[50]l.google.com.
+[50]l.google.com.
+a.[50]l.google.com.
+[50]l.google.com.
+d.[50]l.google.com.
+[50]l.google.com.
+e.[50]l.google.com.
+[50]l.google.com.
+f.[50]l.google.com.
+[50]l.google.com.
+g.[50]l.google.com.
+[92]b.[50]l.google.com.
+[108]a.[50]l.google.com.
+[124]d.[50]l.google.com.
+[140]e.[50]l.google.com.
+[156]f.[50]l.google.com.
+[172]g.[50]l.google.com.
+maps.gstatic.com.
+maps.gstatic.com.
+[12]maps.gstatic.com.
+www2.l.google.com.
+[46]www2.l.google.com.
+[51]l.google.com.
+a.[51]l.google.com.
+[51]l.google.com.
+d.[51]l.google.com.
+[51]l.google.com.
+e.[51]l.google.com.
+[51]l.google.com.
+f.[51]l.google.com.
+[51]l.google.com.
+g.[51]l.google.com.
+[51]l.google.com.
+b.[51]l.google.com.
+[93]a.[51]l.google.com.
+[109]d.[51]l.google.com.
+[125]e.[51]l.google.com.
+[141]f.[51]l.google.com.
+[157]g.[51]l.google.com.
+[173]b.[51]l.google.com.
+www.calgaryherald.com.
+www.calgaryherald.com.
+[12]www.calgaryherald.com.
+calgaryherald.com.
+ns1.canwest.[69]com.
+[55]calgaryherald.com.
+ns2.[88]canwest.[69]com.
+[84]ns1.canwest.[69]com.
+[110]ns2.[88]canwest.[69]com.
+a123.g.akamai.net.
+a123.g.akamai.net.
+[12]a123.g.akamai.net.
+[12]a123.g.akamai.net.
+members.canada.com.
+members.canada.com.
+[12]members.canada.com.
+canada.com.
+ns2.canwest.[59]com.
+[52]canada.com.
+ns1.[78]canwest.[59]com.
+[74]ns2.canwest.[59]com.
+[100]ns1.[78]canwest.[59]com.
+www.canada.com.
+www.canada.com.
+[12]www.canada.com.
+canada.com.
+ns1.canwest.[55]com.
+[48]canada.com.
+ns2.[74]canwest.[55]com.
+[70]ns1.canwest.[55]com.
+[96]ns2.[74]canwest.[55]com.
+s9.addthis.com.
+s9.addthis.com.
+[12]s9.addthis.com.
+wildcard.addthis.com.edgekey.net.
+[44]wildcard.addthis.com.edgekey.net.
+e2943.c.akamaiedge.[73]net.
+[90]e2943.c.akamaiedge.[73]net.
+[96]c.akamaiedge.[73]net.
+n7c.[98]akamaiedge.[73]net.
+[96]c.akamaiedge.[73]net.
+n5c.[98]akamaiedge.[73]net.
+[96]c.akamaiedge.[73]net.
+n8c.[98]akamaiedge.[73]net.
+[96]c.akamaiedge.[73]net.
+n0c.[98]akamaiedge.[73]net.
+[96]c.akamaiedge.[73]net.
+n6c.[98]akamaiedge.[73]net.
+[96]c.akamaiedge.[73]net.
+n1c.[98]akamaiedge.[73]net.
+[96]c.akamaiedge.[73]net.
+n4c.[98]akamaiedge.[73]net.
+[96]c.akamaiedge.[73]net.
+n3c.[98]akamaiedge.[73]net.
+[96]c.akamaiedge.[73]net.
+n2c.[98]akamaiedge.[73]net.
+[139]n7c.[98]akamaiedge.[73]net.
+[157]n5c.[98]akamaiedge.[73]net.
+[175]n8c.[98]akamaiedge.[73]net.
+[193]n0c.[98]akamaiedge.[73]net.
+[211]n6c.[98]akamaiedge.[73]net.
+[229]n1c.[98]akamaiedge.[73]net.
+[247]n4c.[98]akamaiedge.[73]net.
+[265]n3c.[98]akamaiedge.[73]net.
+[283]n2c.[98]akamaiedge.[73]net.
+communities.canada.com.
+communities.canada.com.
+[12]communities.canada.com.
+canada.com.
+ns1.canwest.[63]com.
+[56]canada.com.
+ns2.[82]canwest.[63]com.
+[78]ns1.canwest.[63]com.
+[104]ns2.[82]canwest.[63]com.
+canwestglobal.112.2o7.net.
+beacon.securestudies.com.
+beacon.securestudies.com.
+[12]beacon.securestudies.com.
+beacon.gta.securestudies.com.
+[54]beacon.gta.securestudies.com.
+[61]gta.securestudies.com.
+gta02.iad.[65]securestudies.com.
+[61]gta.securestudies.com.
+gta02.ord.[65]securestudies.com.
+[61]gta.securestudies.com.
+gta01.[118]iad.[65]securestudies.com.
+[61]gta.securestudies.com.
+gta01.[142]ord.[65]securestudies.com.
+[112]gta02.iad.[65]securestudies.com.
+[136]gta02.ord.[65]securestudies.com.
+[160]gta01.[118]iad.[65]securestudies.com.
+[180]gta01.[142]ord.[65]securestudies.com.
+canwestglobal.112.2o7.net.
+[12]canwestglobal.112.2o7.net.
+[12]canwestglobal.112.2o7.net.
+[12]canwestglobal.112.2o7.net.
+[12]canwestglobal.112.2o7.net.
+[12]canwestglobal.112.2o7.net.
+[12]canwestglobal.112.2o7.net.
+[12]canwestglobal.112.2o7.net.
+2o7.net.
+ns1.dal.omniture.com.
+[155]2o7.net.
+ns1.sj1.[182]omniture.com.
+[155]2o7.net.
+ns1.sj2.[182]omniture.com.
+[174]ns1.dal.omniture.com.
+[208]ns1.sj1.[182]omniture.com.
+[230]ns1.sj2.[182]omniture.com.
+s7.addthis.com.
+s7.addthis.com.
+[12]s7.addthis.com.
+wildcard.addthis.com.edgekey.net.
+[44]wildcard.addthis.com.edgekey.net.
+e2943.c.akamaiedge.[73]net.
+[90]e2943.c.akamaiedge.[73]net.
+[96]c.akamaiedge.[73]net.
+n5c.[98]akamaiedge.[73]net.
+[96]c.akamaiedge.[73]net.
+n8c.[98]akamaiedge.[73]net.
+[96]c.akamaiedge.[73]net.
+n0c.[98]akamaiedge.[73]net.
+[96]c.akamaiedge.[73]net.
+n6c.[98]akamaiedge.[73]net.
+[96]c.akamaiedge.[73]net.
+n1c.[98]akamaiedge.[73]net.
+[96]c.akamaiedge.[73]net.
+n4c.[98]akamaiedge.[73]net.
+[96]c.akamaiedge.[73]net.
+n3c.[98]akamaiedge.[73]net.
+[96]c.akamaiedge.[73]net.
+n2c.[98]akamaiedge.[73]net.
+[96]c.akamaiedge.[73]net.
+n7c.[98]akamaiedge.[73]net.
+[139]n5c.[98]akamaiedge.[73]net.
+[157]n8c.[98]akamaiedge.[73]net.
+[175]n0c.[98]akamaiedge.[73]net.
+[193]n6c.[98]akamaiedge.[73]net.
+[211]n1c.[98]akamaiedge.[73]net.
+[229]n4c.[98]akamaiedge.[73]net.
+[247]n3c.[98]akamaiedge.[73]net.
+[265]n2c.[98]akamaiedge.[73]net.
+[283]n7c.[98]akamaiedge.[73]net.
+csi.gstatic.com.
+csi.gstatic.com.
+[12]csi.gstatic.com.
+csi.l.google.com.
+[45]csi.l.google.com.
+[49]l.google.com.
+d.[49]l.google.com.
+[49]l.google.com.
+e.[49]l.google.com.
+[49]l.google.com.
+f.[49]l.google.com.
+[49]l.google.com.
+g.[49]l.google.com.
+[49]l.google.com.
+b.[49]l.google.com.
+[49]l.google.com.
+a.[49]l.google.com.
+[91]d.[49]l.google.com.
+[107]e.[49]l.google.com.
+[123]f.[49]l.google.com.
+[139]g.[49]l.google.com.
+[155]b.[49]l.google.com.
+[171]a.[49]l.google.com.
+www.thestar.com.
+www.thestar.com.
+[12]www.thestar.com.
+[16]thestar.com.
+ns1.[16]thestar.com.
+[16]thestar.com.
+ns2.[16]thestar.com.
+[61]ns1.[16]thestar.com.
+[79]ns2.[16]thestar.com.
+beacon.scorecardresearch.com.
+beacon.scorecardresearch.com.
+[12]beacon.scorecardresearch.com.
+beacon.gta.scorecardresearch.com.
+[58]beacon.gta.scorecardresearch.com.
+[65]gta.scorecardresearch.com.
+gta01.iad.[69]scorecardresearch.com.
+[65]gta.scorecardresearch.com.
+gta02.ord.[69]scorecardresearch.com.
+[65]gta.scorecardresearch.com.
+gta01.[150]ord.[69]scorecardresearch.com.
+[65]gta.scorecardresearch.com.
+gta02.[126]iad.[69]scorecardresearch.com.
+[120]gta01.iad.[69]scorecardresearch.com.
+[144]gta02.ord.[69]scorecardresearch.com.
+[168]gta01.[150]ord.[69]scorecardresearch.com.
+[188]gta02.[126]iad.[69]scorecardresearch.com.
+media.thestar.topscms.com.
+media.thestar.topscms.com.
+[12]media.thestar.topscms.com.
+media.thestar.topscms.com.edgesuite.net.
+[55]media.thestar.topscms.com.edgesuite.net.
+a1520.g.akamai.[91]net.
+[108]a1520.g.akamai.[91]net.
+[108]a1520.g.akamai.[91]net.
+[114]g.akamai.[91]net.
+n0g.[116]akamai.[91]net.
+[114]g.akamai.[91]net.
+n4g.[116]akamai.[91]net.
+[114]g.akamai.[91]net.
+n2g.[116]akamai.[91]net.
+[114]g.akamai.[91]net.
+n5g.[116]akamai.[91]net.
+[114]g.akamai.[91]net.
+n7g.[116]akamai.[91]net.
+[114]g.akamai.[91]net.
+n6g.[116]akamai.[91]net.
+[114]g.akamai.[91]net.
+n8g.[116]akamai.[91]net.
+[114]g.akamai.[91]net.
+n1g.[116]akamai.[91]net.
+[114]g.akamai.[91]net.
+n3g.[116]akamai.[91]net.
+[169]n0g.[116]akamai.[91]net.
+[187]n4g.[116]akamai.[91]net.
+[205]n2g.[116]akamai.[91]net.
+[223]n5g.[116]akamai.[91]net.
+[241]n7g.[116]akamai.[91]net.
+[259]n6g.[116]akamai.[91]net.
+[277]n8g.[116]akamai.[91]net.
+[295]n1g.[116]akamai.[91]net.
+[313]n3g.[116]akamai.[91]net.
+www.addthis.com.
+www.addthis.com.
+[12]www.addthis.com.
+vp-www.addthis.com.
+[45]vp-www.addthis.com.
+[52]addthis.com.
+eur2.akam.net.
+[52]addthis.com.
+usc1.[98]akam.net.
+[52]addthis.com.
+usc2.[98]akam.net.
+[52]addthis.com.
+usw1.[98]akam.net.
+[52]addthis.com.
+usw6.[98]akam.net.
+[52]addthis.com.
+asia3.[98]akam.net.
+[52]addthis.com.
+ns1-33.[98]akam.net.
+[52]addthis.com.
+ns1-43.[98]akam.net.
+[93]eur2.akam.net.
+[120]usc1.[98]akam.net.
+[139]usc2.[98]akam.net.
+[158]usw1.[98]akam.net.
+[177]usw6.[98]akam.net.
+[196]asia3.[98]akam.net.
+[216]ns1-33.[98]akam.net.
+[237]ns1-43.[98]akam.net.
+n.thestar.com.
+n.thestar.com.
+[12]n.thestar.com.
+thestar.com.122.2o7.net.
+[43]thestar.com.122.2o7.net.
+[43]thestar.com.122.2o7.net.
+[43]thestar.com.122.2o7.net.
+[43]thestar.com.122.2o7.net.
+[43]thestar.com.122.2o7.net.
+[43]thestar.com.122.2o7.net.
+[59]2o7.net.
+ns1.sj1.omniture.com.
+[59]2o7.net.
+ns1.sj2.[184]omniture.com.
+[59]2o7.net.
+ns1.dal.[184]omniture.com.
+[176]ns1.sj1.omniture.com.
+[210]ns1.sj2.[184]omniture.com.
+[232]ns1.dal.[184]omniture.com.
+news.therecord.com.
+news.therecord.com.
+[12]news.therecord.com.
+therecord.com.
+ns1.thestar.[62]com.
+[52]therecord.com.
+ns2.[81]thestar.[62]com.
+[77]ns1.thestar.[62]com.
+[103]ns2.[81]thestar.[62]com.
+media.therecord.topscms.com.
+media.therecord.topscms.com.
+[12]media.therecord.topscms.com.
+media.therecord.topscms.com.edgesuite.net.
+[57]media.therecord.topscms.com.edgesuite.net.
+a847.g.akamai.[95]net.
+[112]a847.g.akamai.[95]net.
+[112]a847.g.akamai.[95]net.
+[117]g.akamai.[95]net.
+n2g.[119]akamai.[95]net.
+[117]g.akamai.[95]net.
+n5g.[119]akamai.[95]net.
+[117]g.akamai.[95]net.
+n7g.[119]akamai.[95]net.
+[117]g.akamai.[95]net.
+n6g.[119]akamai.[95]net.
+[117]g.akamai.[95]net.
+n8g.[119]akamai.[95]net.
+[117]g.akamai.[95]net.
+n1g.[119]akamai.[95]net.
+[117]g.akamai.[95]net.
+n3g.[119]akamai.[95]net.
+[117]g.akamai.[95]net.
+n0g.[119]akamai.[95]net.
+[117]g.akamai.[95]net.
+n4g.[119]akamai.[95]net.
+[172]n2g.[119]akamai.[95]net.
+[190]n5g.[119]akamai.[95]net.
+[208]n7g.[119]akamai.[95]net.
+[226]n6g.[119]akamai.[95]net.
+[244]n8g.[119]akamai.[95]net.
+[262]n1g.[119]akamai.[95]net.
+[280]n3g.[119]akamai.[95]net.
+[298]n0g.[119]akamai.[95]net.
+[316]n4g.[119]akamai.[95]net.
+media.therecord.com.
+www.goldbook.ca.
+media.therecord.com.
+[12]media.therecord.com.
+therecord.com.
+ns2.thestar.[63]com.
+[53]therecord.com.
+ns1.[82]thestar.[63]com.
+[78]ns2.thestar.[63]com.
+[104]ns1.[82]thestar.[63]com.
+www.goldbook.ca.
+[12]www.goldbook.ca.
+goldbook.ca.
+[45]goldbook.ca.
+[45]goldbook.ca.
+ns4.everydns.net.
+[45]goldbook.ca.
+ns1.[90]everydns.net.
+[45]goldbook.ca.
+ns2.[90]everydns.net.
+[45]goldbook.ca.
+ns3.[90]everydns.net.
+[86]ns4.everydns.net.
+[116]ns1.[90]everydns.net.
+[134]ns2.[90]everydns.net.
+[152]ns3.[90]everydns.net.
+torstardigital.122.2o7.net.
+torstardigital.122.2o7.net.
+[12]torstardigital.122.2o7.net.
+[12]torstardigital.122.2o7.net.
+[12]torstardigital.122.2o7.net.
+[12]torstardigital.122.2o7.net.
+[12]torstardigital.122.2o7.net.
+[12]torstardigital.122.2o7.net.
+2o7.net.
+ns1.dal.omniture.com.
+[140]2o7.net.
+ns1.sj1.[167]omniture.com.
+[140]2o7.net.
+ns1.sj2.[167]omniture.com.
+[159]ns1.dal.omniture.com.
+[193]ns1.sj1.[167]omniture.com.
+[215]ns1.sj2.[167]omniture.com.
+news.google.ca.
+news.google.ca.
+[12]news.google.ca.
+news.google.com.
+[44]news.google.com.
+news.l.[49]google.com.
+[73]news.l.[49]google.com.
+[78]l.[49]google.com.
+e.[78]l.[49]google.com.
+[78]l.[49]google.com.
+b.[78]l.[49]google.com.
+[78]l.[49]google.com.
+a.[78]l.[49]google.com.
+[78]l.[49]google.com.
+g.[78]l.[49]google.com.
+[78]l.[49]google.com.
+d.[78]l.[49]google.com.
+[78]l.[49]google.com.
+f.[78]l.[49]google.com.
+[110]e.[78]l.[49]google.com.
+[126]b.[78]l.[49]google.com.
+[142]a.[78]l.[49]google.com.
+[158]g.[78]l.[49]google.com.
+[174]d.[78]l.[49]google.com.
+[190]f.[78]l.[49]google.com.
+googleads.g.doubleclick.net.
+googleads.g.doubleclick.net.
+[12]googleads.g.doubleclick.net.
+pagead.l.doubleclick.net.
+[57]pagead.l.doubleclick.net.
+[64]l.doubleclick.net.
+g.l.google.com.
+[64]l.doubleclick.net.
+a.[113]l.google.com.
+[64]l.doubleclick.net.
+b.[113]l.google.com.
+[64]l.doubleclick.net.
+d.[113]l.google.com.
+[64]l.doubleclick.net.
+e.[113]l.google.com.
+[64]l.doubleclick.net.
+f.[113]l.google.com.
+[111]g.l.google.com.
+[139]a.[113]l.google.com.
+[155]b.[113]l.google.com.
+[171]d.[113]l.google.com.
+[187]e.[113]l.google.com.
+[203]f.[113]l.google.com.
+www.montrealgazette.com.
+www.montrealgazette.com.
+[12]www.montrealgazette.com.
+montrealgazette.com.
+ns2.canwest.[73]com.
+[57]montrealgazette.com.
+ns1.[92]canwest.[73]com.
+[88]ns2.canwest.[73]com.
+[114]ns1.[92]canwest.[73]com.
+a123.g.akamai.net.
+a123.g.akamai.net.
+[12]a123.g.akamai.net.
+[12]a123.g.akamai.net.
+members.canada.com.
+members.canada.com.
+[12]members.canada.com.
+canada.com.
+ns2.canwest.[59]com.
+[52]canada.com.
+ns1.[78]canwest.[59]com.
+[74]ns2.canwest.[59]com.
+[100]ns1.[78]canwest.[59]com.
+www.cbc.ca.
+www.cbc.ca.
+[12]www.cbc.ca.
+www.cbc.ca.edgesuite.net.
+[40]www.cbc.ca.edgesuite.net.
+a1849.gc.akamai.[61]net.
+[78]a1849.gc.akamai.[61]net.
+[78]a1849.gc.akamai.[61]net.
+[84]gc.akamai.[61]net.
+n6gc.[87]akamai.[61]net.
+[84]gc.akamai.[61]net.
+n1gc.[87]akamai.[61]net.
+[84]gc.akamai.[61]net.
+n4gc.[87]akamai.[61]net.
+[84]gc.akamai.[61]net.
+n8gc.[87]akamai.[61]net.
+[84]gc.akamai.[61]net.
+n2gc.[87]akamai.[61]net.
+[84]gc.akamai.[61]net.
+n0gc.[87]akamai.[61]net.
+[84]gc.akamai.[61]net.
+n7gc.[87]akamai.[61]net.
+[84]gc.akamai.[61]net.
+n5gc.[87]akamai.[61]net.
+[84]gc.akamai.[61]net.
+n3gc.[87]akamai.[61]net.
+[140]n6gc.[87]akamai.[61]net.
+[159]n1gc.[87]akamai.[61]net.
+[178]n4gc.[87]akamai.[61]net.
+[197]n8gc.[87]akamai.[61]net.
+[216]n2gc.[87]akamai.[61]net.
+[235]n0gc.[87]akamai.[61]net.
+[254]n7gc.[87]akamai.[61]net.
+[273]n5gc.[87]akamai.[61]net.
+[292]n3gc.[87]akamai.[61]net.
+a.cbc.ca.
+a.cbc.ca.
+[12]a.cbc.ca.
+ehg-cbc.hitbox.com.
+[38]ehg-cbc.hitbox.com.
+[46]hitbox.com.
+dns06.omniture.[53]com.
+[46]hitbox.com.
+dns05.[92]omniture.[53]com.
+[46]hitbox.com.
+dns04.[92]omniture.[53]com.
+[46]hitbox.com.
+dns03.[92]omniture.[53]com.
+[46]hitbox.com.
+dns02.[92]omniture.[53]com.
+[46]hitbox.com.
+dns01.[92]omniture.[53]com.
+[86]dns06.omniture.[53]com.
+[115]dns05.[92]omniture.[53]com.
+[135]dns04.[92]omniture.[53]com.
+[155]dns03.[92]omniture.[53]com.
+[175]dns02.[92]omniture.[53]com.
+[195]dns01.[92]omniture.[53]com.
+assets.loomia.com.
+assets.loomia.com.
+[12]assets.loomia.com.
+a.[19]loomia.com.
+[47]a.[19]loomia.com.
+[19]loomia.com.
+ns15.dnsmadeeasy.[26]com.
+[19]loomia.com.
+ns14.[84]dnsmadeeasy.[26]com.
+[19]loomia.com.
+ns12.[84]dnsmadeeasy.[26]com.
+[19]loomia.com.
+ns11.[84]dnsmadeeasy.[26]com.
+[19]loomia.com.
+ns13.[84]dnsmadeeasy.[26]com.
+[19]loomia.com.
+ns10.[84]dnsmadeeasy.[26]com.
+recs-social.loomia.com.
+recs-social.loomia.com.
+[12]recs-social.loomia.com.
+rec-assets.[24]loomia.com.
+[52]rec-assets.[24]loomia.com.
+[24]loomia.com.
+ns14.dnsmadeeasy.[31]com.
+[24]loomia.com.
+ns11.[98]dnsmadeeasy.[31]com.
+[24]loomia.com.
+ns12.[98]dnsmadeeasy.[31]com.
+[24]loomia.com.
+ns15.[98]dnsmadeeasy.[31]com.
+[24]loomia.com.
+ns10.[98]dnsmadeeasy.[31]com.
+[24]loomia.com.
+ns13.[98]dnsmadeeasy.[31]com.
+e1.clearspring.com.
+static-cache.loomia.com.
+static-cache.loomia.com.
+[12]static-cache.loomia.com.
+static-cache.loomia.com.edgesuite.net.
+[53]static-cache.loomia.com.edgesuite.net.
+a298.g.akamai.[87]net.
+[104]a298.g.akamai.[87]net.
+[104]a298.g.akamai.[87]net.
+[109]g.akamai.[87]net.
+n4g.[111]akamai.[87]net.
+[109]g.akamai.[87]net.
+n2g.[111]akamai.[87]net.
+[109]g.akamai.[87]net.
+n5g.[111]akamai.[87]net.
+[109]g.akamai.[87]net.
+n7g.[111]akamai.[87]net.
+[109]g.akamai.[87]net.
+n6g.[111]akamai.[87]net.
+[109]g.akamai.[87]net.
+n8g.[111]akamai.[87]net.
+[109]g.akamai.[87]net.
+n1g.[111]akamai.[87]net.
+[109]g.akamai.[87]net.
+n3g.[111]akamai.[87]net.
+[109]g.akamai.[87]net.
+n0g.[111]akamai.[87]net.
+[164]n4g.[111]akamai.[87]net.
+[182]n2g.[111]akamai.[87]net.
+[200]n5g.[111]akamai.[87]net.
+[218]n7g.[111]akamai.[87]net.
+[236]n6g.[111]akamai.[87]net.
+[254]n8g.[111]akamai.[87]net.
+[272]n1g.[111]akamai.[87]net.
+[290]n3g.[111]akamai.[87]net.
+[308]n0g.[111]akamai.[87]net.
+e1.clearspring.com.
+[12]e1.clearspring.com.
+[15]clearspring.com.
+usc2.akam.net.
+[15]clearspring.com.
+usw1.[69]akam.net.
+[15]clearspring.com.
+usw6.[69]akam.net.
+[15]clearspring.com.
+asia3.[69]akam.net.
+[15]clearspring.com.
+ns1-33.[69]akam.net.
+[15]clearspring.com.
+ns1-43.[69]akam.net.
+[15]clearspring.com.
+eur2.[69]akam.net.
+[15]clearspring.com.
+usc1.[69]akam.net.
+csi.gstatic.com.
+csi.gstatic.com.
+[12]csi.gstatic.com.
+csi.l.google.com.
+[45]csi.l.google.com.
+[49]l.google.com.
+b.[49]l.google.com.
+[49]l.google.com.
+e.[49]l.google.com.
+[49]l.google.com.
+d.[49]l.google.com.
+[49]l.google.com.
+a.[49]l.google.com.
+[49]l.google.com.
+f.[49]l.google.com.
+[49]l.google.com.
+g.[49]l.google.com.
+[91]b.[49]l.google.com.
+[107]e.[49]l.google.com.
+[123]d.[49]l.google.com.
+[139]a.[49]l.google.com.
+[155]f.[49]l.google.com.
+[171]g.[49]l.google.com.
+www.gstatic.com.
+www.gstatic.com.
+[12]www.gstatic.com.
+www2.l.google.com.
+[45]www2.l.google.com.
+[50]l.google.com.
+d.[50]l.google.com.
+[50]l.google.com.
+f.[50]l.google.com.
+[50]l.google.com.
+e.[50]l.google.com.
+[50]l.google.com.
+b.[50]l.google.com.
+[50]l.google.com.
+a.[50]l.google.com.
+[50]l.google.com.
+g.[50]l.google.com.
+[92]d.[50]l.google.com.
+[108]f.[50]l.google.com.
+[124]e.[50]l.google.com.
+[140]b.[50]l.google.com.
+[156]a.[50]l.google.com.
+[172]g.[50]l.google.com.
+i.ytimg.com.
+i.ytimg.com.
+[12]i.ytimg.com.
+ytimg.l.google.com.
+[41]ytimg.l.google.com.
+[47]l.google.com.
+b.[47]l.google.com.
+[47]l.google.com.
+a.[47]l.google.com.
+[47]l.google.com.
+g.[47]l.google.com.
+[47]l.google.com.
+d.[47]l.google.com.
+[47]l.google.com.
+f.[47]l.google.com.
+[47]l.google.com.
+e.[47]l.google.com.
+[89]b.[47]l.google.com.
+[105]a.[47]l.google.com.
+[121]g.[47]l.google.com.
+[137]d.[47]l.google.com.
+[153]f.[47]l.google.com.
+[169]e.[47]l.google.com.
+news.bbc.co.uk.
+news.bbc.co.uk.
+[12]news.bbc.co.uk.
+newswww.bbc.net.uk.
+[44]newswww.bbc.net.uk.
+[52]bbc.net.uk.
+ns0.rbsov.bbc.co.[60]uk.
+[52]bbc.net.uk.
+ns0.thdo.[102]bbc.co.[60]uk.
+[92]ns0.rbsov.bbc.co.[60]uk.
+[123]ns0.thdo.[102]bbc.co.[60]uk.
+node1.bbcimg.co.uk.
+node1.bbcimg.co.uk.
+[12]node1.bbcimg.co.uk.
+img.bbc.net.uk.
+[48]img.bbc.net.uk.
+[52]bbc.net.uk.
+ns0.rbsov.bbc.co.[60]uk.
+[52]bbc.net.uk.
+ns0.thdo.[102]bbc.co.[60]uk.
+[92]ns0.rbsov.bbc.co.[60]uk.
+[123]ns0.thdo.[102]bbc.co.[60]uk.
+newsimg.bbc.co.uk.
+newsimg.bbc.co.uk.
+[12]newsimg.bbc.co.uk.
+newsimg.bbc.net.uk.
+[47]newsimg.bbc.net.uk.
+news.bbc.co.uk.edgesuite.net.
+[79]news.bbc.co.uk.edgesuite.net.
+a1733.g.akamai.[104]net.
+[121]a1733.g.akamai.[104]net.
+[121]a1733.g.akamai.[104]net.
+[127]g.akamai.[104]net.
+n7g.[129]akamai.[104]net.
+[127]g.akamai.[104]net.
+n6g.[129]akamai.[104]net.
+[127]g.akamai.[104]net.
+n8g.[129]akamai.[104]net.
+[127]g.akamai.[104]net.
+n1g.[129]akamai.[104]net.
+[127]g.akamai.[104]net.
+n3g.[129]akamai.[104]net.
+[127]g.akamai.[104]net.
+n0g.[129]akamai.[104]net.
+[127]g.akamai.[104]net.
+n4g.[129]akamai.[104]net.
+[127]g.akamai.[104]net.
+n2g.[129]akamai.[104]net.
+[127]g.akamai.[104]net.
+n5g.[129]akamai.[104]net.
+[182]n7g.[129]akamai.[104]net.
+[200]n6g.[129]akamai.[104]net.
+[218]n8g.[129]akamai.[104]net.
+[236]n1g.[129]akamai.[104]net.
+[254]n3g.[129]akamai.[104]net.
+[272]n0g.[129]akamai.[104]net.
+[290]n4g.[129]akamai.[104]net.
+[308]n2g.[129]akamai.[104]net.
+[326]n5g.[129]akamai.[104]net.
+stats.bbc.co.uk.
+stats.bbc.co.uk.
+[12]stats.bbc.co.uk.
+[12]stats.bbc.co.uk.
+bbc.co.uk.
+ns1.thls.[65]bbc.co.uk.
+[65]bbc.co.uk.
+ns1.thdo.[65]bbc.co.uk.
+[65]bbc.co.uk.
+ns1.rbsov.[65]bbc.co.uk.
+[65]bbc.co.uk.
+ns1.[65]bbc.co.uk.
+[86]ns1.thls.[65]bbc.co.uk.
+[109]ns1.thdo.[65]bbc.co.uk.
+[132]ns1.rbsov.[65]bbc.co.uk.
+[156]ns1.[65]bbc.co.uk.
+visualscience.external.bbc.co.uk.
+js.revsci.net.
+visualscience.external.bbc.co.uk.
+[12]visualscience.external.bbc.co.uk.
+csvtm.interactionscience.com.
+[62]csvtm.interactionscience.com.
+[68]interactionscience.com.
+ns1.sj1.omniture.[87]com.
+[68]interactionscience.com.
+ns1.sj2.[128]omniture.[87]com.
+[68]interactionscience.com.
+ns1.dal.[128]omniture.[87]com.
+[120]ns1.sj1.omniture.[87]com.
+[151]ns1.sj2.[128]omniture.[87]com.
+[173]ns1.dal.[128]omniture.[87]com.
+js.revsci.net.
+[12]js.revsci.net.
+[15]revsci.net.
+ns3.p16.dynect.[22]net.
+[15]revsci.net.
+ns4.[63]p16.dynect.[22]net.
+[15]revsci.net.
+ns2.[63]p16.dynect.[22]net.
+[15]revsci.net.
+ns1.[63]p16.dynect.[22]net.
+pix04.revsci.net.
+pix04.revsci.net.
+[12]pix04.revsci.net.
+[18]revsci.net.
+ns4.p16.dynect.[25]net.
+[18]revsci.net.
+ns1.[66]p16.dynect.[25]net.
+[18]revsci.net.
+ns3.[66]p16.dynect.[25]net.
+[18]revsci.net.
+ns2.[66]p16.dynect.[25]net.
+pixel.quantserve.com.
+pixel.quantserve.com.
+[12]pixel.quantserve.com.
+map-pb.quantserve.com.akadns.net.
+[50]map-pb.quantserve.com.akadns.net.
+ac-na.[57]quantserve.com.akadns.net.
+[96]ac-na.[57]quantserve.com.akadns.net.
+[96]ac-na.[57]quantserve.com.akadns.net.
+[96]ac-na.[57]quantserve.com.akadns.net.
+[96]ac-na.[57]quantserve.com.akadns.net.
+[96]ac-na.[57]quantserve.com.akadns.net.
+[96]ac-na.[57]quantserve.com.akadns.net.
+[96]ac-na.[57]quantserve.com.akadns.net.
+[72]akadns.net.
+za.akadns.org.
+[72]akadns.net.
+zb.[231]akadns.org.
+[72]akadns.net.
+zc.[231]akadns.org.
+[72]akadns.net.
+zd.[231]akadns.org.
+[72]akadns.net.
+asia9.[72]akadns.net.
+[72]akadns.net.
+eur1.[72]akadns.net.
+[72]akadns.net.
+use3.[72]akadns.net.
+[72]akadns.net.
+use4.[72]akadns.net.
+[72]akadns.net.
+usw2.[72]akadns.net.
+[228]za.akadns.org.
+[255]zb.[231]akadns.org.
+[272]zc.[231]akadns.org.
+[289]zd.[231]akadns.org.
+[306]asia9.[72]akadns.net.
+[326]eur1.[72]akadns.net.
+[345]use3.[72]akadns.net.
+www.vancouversun.com.
+www.vancouversun.com.
+[12]www.vancouversun.com.
+vancouversun.com.
+ns1.canwest.[67]com.
+[54]vancouversun.com.
+ns2.[86]canwest.[67]com.
+[82]ns1.canwest.[67]com.
+[108]ns2.[86]canwest.[67]com.
+www.scan.nowpublic.com.
+www.scan.nowpublic.com.
+[12]www.scan.nowpublic.com.
+a1.panthercdn.com.
+[52]a1.panthercdn.com.
+[55]panthercdn.com.
+ns1.[55]panthercdn.com.
+[55]panthercdn.com.
+ns2.[55]panthercdn.com.
+[99]ns1.[55]panthercdn.com.
+[117]ns2.[55]panthercdn.com.
+a123.g.akamai.net.
+a123.g.akamai.net.
+[12]a123.g.akamai.net.
+[12]a123.g.akamai.net.
+feeds.theplatform.com.
+canwestglobal.112.2o7.net.
+beacon.securestudies.com.
+canwestglobal.112.2o7.net.
+[12]canwestglobal.112.2o7.net.
+[12]canwestglobal.112.2o7.net.
+[12]canwestglobal.112.2o7.net.
+[12]canwestglobal.112.2o7.net.
+[12]canwestglobal.112.2o7.net.
+[12]canwestglobal.112.2o7.net.
+[12]canwestglobal.112.2o7.net.
+2o7.net.
+ns1.sj1.omniture.com.
+[155]2o7.net.
+ns1.sj2.[182]omniture.com.
+[155]2o7.net.
+ns1.dal.[182]omniture.com.
+[174]ns1.sj1.omniture.com.
+[208]ns1.sj2.[182]omniture.com.
+[230]ns1.dal.[182]omniture.com.
+beacon.securestudies.com.
+[12]beacon.securestudies.com.
+beacon.gta.securestudies.com.
+[54]beacon.gta.securestudies.com.
+[61]gta.securestudies.com.
+gta02.ord.[65]securestudies.com.
+[61]gta.securestudies.com.
+gta01.iad.[65]securestudies.com.
+[61]gta.securestudies.com.
+gta01.[118]ord.[65]securestudies.com.
+[61]gta.securestudies.com.
+gta02.[142]iad.[65]securestudies.com.
+[112]gta02.ord.[65]securestudies.com.
+[136]gta01.iad.[65]securestudies.com.
+[160]gta01.[118]ord.[65]securestudies.com.
+[180]gta02.[142]iad.[65]securestudies.com.
+feeds.theplatform.com.
+[12]feeds.theplatform.com.
+[18]theplatform.com.
+sea1tpgtm01.[18]theplatform.com.
+[18]theplatform.com.
+bfi1tpgtm01.[18]theplatform.com.
+[67]sea1tpgtm01.[18]theplatform.com.
+[93]bfi1tpgtm01.[18]theplatform.com.
+s7.addthis.com.
+s7.addthis.com.
+[12]s7.addthis.com.
+wildcard.addthis.com.edgekey.net.
+[44]wildcard.addthis.com.edgekey.net.
+e2943.c.akamaiedge.[73]net.
+[90]e2943.c.akamaiedge.[73]net.
+[96]c.akamaiedge.[73]net.
+n5c.[98]akamaiedge.[73]net.
+[96]c.akamaiedge.[73]net.
+n8c.[98]akamaiedge.[73]net.
+[96]c.akamaiedge.[73]net.
+n0c.[98]akamaiedge.[73]net.
+[96]c.akamaiedge.[73]net.
+n6c.[98]akamaiedge.[73]net.
+[96]c.akamaiedge.[73]net.
+n1c.[98]akamaiedge.[73]net.
+[96]c.akamaiedge.[73]net.
+n4c.[98]akamaiedge.[73]net.
+[96]c.akamaiedge.[73]net.
+n3c.[98]akamaiedge.[73]net.
+[96]c.akamaiedge.[73]net.
+n2c.[98]akamaiedge.[73]net.
+[96]c.akamaiedge.[73]net.
+n7c.[98]akamaiedge.[73]net.
+[139]n5c.[98]akamaiedge.[73]net.
+[157]n8c.[98]akamaiedge.[73]net.
+[175]n0c.[98]akamaiedge.[73]net.
+[193]n6c.[98]akamaiedge.[73]net.
+[211]n1c.[98]akamaiedge.[73]net.
+[229]n4c.[98]akamaiedge.[73]net.
+[247]n3c.[98]akamaiedge.[73]net.
+[265]n2c.[98]akamaiedge.[73]net.
+[283]n7c.[98]akamaiedge.[73]net.
+ad.doubleclick.net.
+ad.doubleclick.net.
+[12]ad.doubleclick.net.
+dart-ad.l.doubleclick.net.
+[48]dart-ad.l.doubleclick.net.
+[48]dart-ad.l.doubleclick.net.
+[56]l.doubleclick.net.
+g.l.google.com.
+[56]l.doubleclick.net.
+a.[121]l.google.com.
+[56]l.doubleclick.net.
+b.[121]l.google.com.
+[56]l.doubleclick.net.
+d.[121]l.google.com.
+[56]l.doubleclick.net.
+e.[121]l.google.com.
+[56]l.doubleclick.net.
+f.[121]l.google.com.
+[119]g.l.google.com.
+[147]a.[121]l.google.com.
+[163]b.[121]l.google.com.
+[179]d.[121]l.google.com.
+[195]e.[121]l.google.com.
+[211]f.[121]l.google.com.
+*** SUCCESS ***
diff --git a/test/generate1.lm b/test/generate1.lm
new file mode 100644
index 00000000..54a342a4
--- /dev/null
+++ b/test/generate1.lm
@@ -0,0 +1,773 @@
+context generate
+ # Regular definitions
+ rl ident_char /[a-zA-Z_]/
+
+ # List used as a stack of indentations.
+ struct int_el
+ Int: int
+ list_el el
+ end
+ IndentStack: list<int_el>
+
+ # Has a newline been sent for this '\n' .. whitespace match.
+ newline_sent: int
+
+ # Tokens.
+ lex
+ # Python keywords.
+ literal `and `del `from `not `while `as `elif `global `or
+ `with `assert `else `if `pass `yield `break `except
+ `import `print `class `exec `in `raise `continue
+ `finally `is `return `def `for `lambda `try
+
+ # Identifiers
+ rl lowercase /'a'..'z'/
+ rl uppercase /'A'..'Z'/
+ rl letter /lowercase | uppercase/
+ token identifier /(letter|'_') (letter | digit | '_')*/
+
+ # Literals
+ rl escapeseq /'\\' any /
+ rl longstringchar /[^\\]/
+ rl shortstringchar_s /[^\\\n']/
+ rl shortstringchar_d /[^\\\n"]/
+ rl longstringitem /longstringchar | escapeseq/
+ rl shortstringitem_s /shortstringchar_s | escapeseq/
+ rl shortstringitem_d /shortstringchar_d | escapeseq/
+ rl longstring /"'''" longstringitem* :>> "'''" | '"""' longstringitem* :>> '"""'/
+ rl shortstring /"'" shortstringitem_s* "'" | '"' shortstringitem_d* '"'/
+ rl stringprefix /"r" | "u" | "ur" | "R" | "U" | "UR" | "Ur" | "uR"/
+ token stringliteral /stringprefix? (shortstring | longstring)/
+
+ # Integers
+ rl hexdigit /digit | 'a'..'f' | 'A'..'F'/
+ rl octdigit /'0'..'7'/
+ rl nonzerodigit /'1'..'9'/
+ rl hexinteger /'0' ('x' | 'X') hexdigit+/
+ rl octinteger /'0' octdigit+/
+ rl decimalinteger /nonzerodigit digit* | '0'/
+ token integer /decimalinteger | octinteger | hexinteger/
+ token longinteger /integer ('l' | 'L')/
+
+ # Floats.
+ rl exponent /('e' | 'E') ('+' | '-')? digit+/
+ rl fraction /'.' digit+/
+ rl intpart /digit+/
+ rl pointfloat /intpart? fraction | intpart '.'/
+ rl exponentfloat /(intpart | pointfloat) exponent/
+ token floatnumber /pointfloat | exponentfloat/
+
+ # Imaginaries.
+ token imagnumber /(floatnumber | intpart) ("j" | "J")/
+
+ # Operators.
+ literal `+ `- `* `** `/ `// `% `<< `>> `& `| `^
+ `~ `< `> `<= `>= `== `!= `<>
+
+ # Delimiters
+ literal `( `) `[ `] `{ `} `@ `, `: `. `` `= `;
+ `+= `-= `*= `/= `//= `%= `&= `|= `^= `>>= `<<=
+ `**=
+
+ literal `...
+
+ # In general whitespace is ignored.
+ ignore WS /' '+/
+
+ # Find and ignore entire blank lines.
+ token BLANK_LINE
+ / '\n' [ \t]* ('#' [^\n]*)? '\n' /
+ {
+ # Need to shorten to take off the newline.
+ # Turn it into ignore.
+ input->push_ignore( make_token( typeid<WS> input->pull(match_length - 1) ) )
+ }
+
+ # Find and ignore comments.
+ token COMMENT
+ / '#' [^\n]* '\n' /
+ {
+ # Need to shorten to take off the newline. Turn it into ignore.
+ input->push_ignore( make_token( typeid<WS> input->pull(match_length - 1) ) )
+ }
+
+ # These tokens are generated
+ token INDENT //
+ token DEDENT //
+ token NEWLINE //
+ ignore IND_WS //
+
+ token INDENTATION
+ /'\n' [ \t]*/
+ {
+ # We have squared up INDENTs and DEDENTs. Ignore the entire match.
+ input->push_ignore( make_token( typeid<WS> input->pull(match_length) ) )
+
+ # We have already sent the newline, compute the indentation level.
+ data_length: int = match_length - 1
+
+ Top: int_el = IndentStack->top
+ if data_length > Top->Int {
+ # The indentation level is more than the level on the top
+ # of the stack. This is an indent event. Send as an INDENT.
+ input->push( make_token( typeid<INDENT> '' ) )
+
+ # Push to the stack as per python manual.
+ IntEl: int_el = new int_el
+ IntEl->Int = data_length
+ IndentStack->push( IntEl )
+ } else {
+ while data_length < Top->Int {
+ # The indentation level is less than the level on the top of
+ # the stack. Pop the level and send one dedent. This flow of
+ # control will execute until we find the right indentation level
+ # to match up with.
+ IndentStack->pop()
+
+ # Send as a DEDENT
+ input->push( make_token( typeid<DEDENT> '' ) )
+
+ Top = IndentStack->top
+ }
+ }
+
+ # FIXME: if data.length is now > top of stack then error. This
+ # means the outdent does not match anything.
+
+ # First the newline.
+ input->push( make_token( typeid<NEWLINE> '' ) )
+ }
+ end
+
+ # Blank lines or comment lines at the beginning of the file.
+ token LEADER / ( [ \t]* ('#' [^\n]*)? '\n' )* /
+
+ # Ordering productions for resolving ambiguities.
+ def O1 []
+ def O2 []
+
+ def start
+ [file_input]
+
+ def file_input
+ [file_input_forms*]
+
+ def file_input_forms
+ [statement]
+ | [NEWLINE]
+
+ def statement
+ [stmt_list NEWLINE]
+ | [compound_stmt]
+
+ def stmt_list
+ [simple_stmt another_stmt* opt_semi]
+
+ def another_stmt
+ [`; simple_stmt]
+
+ def opt_semi
+ [`;]
+ | []
+
+ def suite
+ [stmt_list NEWLINE]
+ | [NEWLINE INDENT statement_seq DEDENT]
+
+ def statement_seq
+ [statement_seq statement]
+ | [statement]
+
+ def compound_stmt
+ [if_stmt]
+ | [while_stmt]
+ | [for_stmt]
+ | [funcdef]
+
+ def if_stmt
+ [`if expression `: suite elif_part* opt_else_part]
+
+ def elif_part
+ [`elif expression `: suite]
+
+ def opt_else_part
+ [`else `: suite]
+ | []
+
+ def while_stmt
+ [`while expression `: suite opt_else_part]
+
+ def for_stmt
+ [`for target_list `in expression_list `: suite opt_else_part]
+
+ def funcdef
+ [`def funcname `( opt_parameter_list `) `: suite]
+
+ def funcname
+ [identifier]
+
+ def dotted_name
+ [dotted_name `. identifier]
+ | [identifier]
+
+ def opt_parameter_list
+ [parameter_list]
+ | []
+
+ def parameter_list
+ [defparameter_list defparameter opt_comma]
+
+ def defparameter_list
+ [defparameter_list defparameter `,]
+ | []
+
+ def defparameter
+ [parameter]
+ | [parameter `= expression]
+
+ def sublist
+ [sublist_pl opt_comma]
+
+ def sublist_pl
+ [sublist_pl `, parameter]
+ | [parameter]
+
+ def parameter
+ [identifier]
+ | [`( sublist `)]
+
+ def classname
+ [identifier]
+
+ def simple_stmt
+ [expression_stmt]
+ | [assignment_stmt]
+ | [print_stmt]
+
+ def expression_stmt
+ [expression_list]
+
+ def assignment_stmt
+ [target_equals_list expression_list]
+
+ def target_equals_list
+ [target_equals_list target_equals]
+ | [target_equals]
+
+ def target_equals
+ [target_list `=]
+
+ def target_list
+ [target_list_core opt_comma]
+
+ def target_list_core
+ [target_list_core `, target]
+ | [target]
+
+ def target
+ [target_atom target_ext_rep]
+
+ def target_atom
+ [identifier]
+ | [`( target_list `)]
+ | [`[ target_list `]]
+
+ def target_ext_rep
+ [target_ext target_ext_rep]
+ | []
+
+ def target_ext
+ [attributeref]
+ | [O1 subscription]
+ | [O2 slicing]
+
+ def print_stmt
+ [`print opt_expression_list]
+
+ def opt_expression_list
+ [expression_list]
+ | []
+
+ def expression_list
+ [expression_list_core opt_comma]
+
+ def expression_list_core
+ [expression_list_core `, expression]
+ | [expression]
+
+ def opt_comma
+ [`,]
+ | []
+
+ def expression
+ [or_test `if or_test `else test]
+ | [or_test]
+ | [lambda_form]
+
+ def or_test
+ [or_test `or and_test]
+ | [and_test]
+
+ def and_test
+ [and_test `and not_test]
+ | [not_test]
+
+ def not_test
+ [comparison]
+ | [`not not_test]
+
+ def lambda_form
+ [`lambda opt_parameter_list `: expression]
+
+ def test
+ [or_test]
+ | [lambda_form]
+
+ def comparison
+ [or_expr comparison_part*]
+
+ def comparison_part
+ [comp_operator or_expr]
+
+ def comp_operator
+ [`<] | [`>] | [`==] | [`>=] | [`<=] | [`<>] | [`!=] | [`is] |
+ [`is `not] | [`in] | [`not `in]
+
+ def or_expr
+ [primary]
+
+ def primary
+ [atom primary_ext_rep]
+
+ def atom
+ [identifier]
+ | [pyliteral]
+ | [enclosure]
+
+ def primary_ext_rep
+ [primary_ext primary_ext_rep]
+ | []
+
+ def primary_ext
+ [attributeref]
+ | [O1 subscription]
+ | [O2 slicing]
+ | [call]
+
+ def pyliteral
+ [stringliteral]
+ | [integer]
+ | [longinteger]
+ | [floatnumber]
+ | [imagnumber]
+
+ def enclosure
+ [parenth_form]
+ | [list_display]
+ | [generator_expression]
+ | [dict_display]
+ | [string_conversion]
+
+ def parenth_form
+ [`( opt_expression_list `)]
+
+ def list_display
+ [`[ opt_listmaker `]]
+
+ def opt_listmaker
+ [listmaker]
+ | []
+
+ def listmaker
+ [expression list_for]
+ | [expression listmaker_ext* opt_comma]
+
+ def listmaker_ext
+ [`, expression]
+
+ def opt_list_iter
+ [list_iter]
+ | []
+
+ def list_iter
+ [list_for]
+ | [list_if]
+
+ def list_if
+ [`if test opt_list_iter]
+
+ def list_for
+ [`for expression_list `in testlist opt_list_iter]
+
+ def testlist
+ [test testlist_ext* opt_comma]
+
+ def testlist_ext
+ [`, test ]
+
+ def generator_expression
+ [`( test genexpr_for `)]
+
+ def genexpr_for
+ [`for expression_list `in test opt_genexpr_iter]
+
+ def opt_genexpr_iter
+ [genexpr_iter]
+ | []
+
+ def genexpr_iter
+ [genexpr_for]
+ | [genexpr_if]
+
+ def genexpr_if
+ [`if test opt_genexpr_iter]
+
+ def dict_display
+ [`{ opt_key_datum_list `}]
+
+ def opt_key_datum_list
+ [key_datum_list]
+ | []
+
+ def key_datum_list
+ [key_datum key_datum_list_ext* opt_comma]
+
+ def key_datum_list_ext
+ [`, key_datum]
+
+ def key_datum
+ [expression `: expression]
+
+ def string_conversion
+ [`` expression_list ``]
+
+ def attributeref
+ [`. identifier]
+
+ def subscription
+ [`[ expression_list `]]
+
+ # The natural ordered choice does not suffice here. Must force it.
+
+ def slicing
+ [simple_slicing]
+ | [extended_slicing]
+
+ def simple_slicing
+ [`[ short_slice `]]
+
+ def extended_slicing
+ [`[ slice_list `]]
+
+ def slice_list
+ [slice_item slice_list_ext* opt_comma]
+
+ def slice_list_ext
+ [`, slice_item]
+
+ def slice_item
+ [expression]
+ | [proper_slice]
+ | [ellipsis]
+
+ def proper_slice
+ [short_slice]
+ | [long_slice]
+
+ def short_slice
+ [`:]
+ | [`: upper_bound]
+ | [lower_bound `:]
+ | [lower_bound `: upper_bound]
+
+ def long_slice
+ [short_slice `: stride]
+ | [short_slice `:]
+
+ def lower_bound
+ [expression]
+
+ def upper_bound
+ [expression]
+
+ def stride
+ [expression]
+
+ def ellipsis
+ [`...]
+
+ def call
+ [`( opt_argument_list `)]
+
+ def opt_argument_list
+ [argument_list opt_comma]
+ | []
+
+ def argument_list
+ [positional_arguments opt_comma_keyword_arguments]
+ | [keyword_arguments]
+
+ def positional_arguments
+ [positional_arguments `, expression]
+ | [expression]
+
+ def opt_comma_keyword_arguments
+ [`, keyword_arguments]
+ | []
+
+ def keyword_arguments
+ [keyword_arguments `, keyword_item]
+ | [keyword_item]
+
+ def keyword_item
+ [identifier `= expression]
+
+end # generate
+
+int print_stmts( S: generate::start )
+{
+ for Stmt: generate::statement in S
+ print( 'STMT: ' ^Stmt '\n' )
+}
+
+int print_target_subscriptions_and_slicings( Start: generate::start )
+{
+ for TI: generate::target_ext in Start {
+ if match TI [generate::subscription] {
+ print( 'TARGET SUBSCRIPTION: ' ^TI '\n' )
+ }
+
+ if match TI [generate::simple_slicing] {
+ print( 'TARGET SIMPLE SLICING: ' ^TI '\n' )
+ }
+
+ if match TI [generate::extended_slicing] {
+ print( 'TARGET EXTENDED SLICING: ' ^TI '\n' )
+ }
+ }
+
+}
+
+int print_primary_subscriptions_and_slicings( Start: generate::start )
+{
+ for PI: generate::primary_ext in Start {
+ if match PI [generate::subscription] {
+ print( 'PRIMARY SUBSCRIPTION: ' ^PI '\n' )
+ }
+
+ if match PI [generate::simple_slicing] {
+ print( 'PRIMARY SIMPLE SLICING: ' ^PI '\n' )
+ }
+
+ if match PI [generate::extended_slicing] {
+ print( 'PRIMARY EXTENDED SLICING: ' ^PI '\n' )
+ }
+ }
+}
+
+Generate: generate = new generate
+
+# List used as a stack of indentations.
+Generate->IndentStack = new list<generate::int_el>
+IntEl: generate::int_el = new generate::int_el
+IntEl->Int = 0
+Generate->IndentStack->push( IntEl )
+
+# Has a newline been sent for this '\n' .. whitespace match.
+Generate->newline_sent = 0
+
+parse S: generate::start(Generate)[ stdin ]
+
+print( '*** SUCCESS ***\n' )
+print( ^S '\n' )
+print( '***\n' )
+print_stmts( S )
+print_target_subscriptions_and_slicings( S )
+print_primary_subscriptions_and_slicings( S )
+print( '*** SUCCESS ***\n' )
+##### IN #####
+
+# dude, this is a comment
+ # some more
+hello
+def dude():
+ yes
+ awesome;
+
+ # Here we have a comment
+ def realy_awesome(): # hi there
+ in_more
+
+ same_level
+ def one_liner(): first; second # both inside one_liner
+
+ back_down
+
+last_statement
+
+# dude, this is a comment
+ # some more
+hello
+if 1:
+ yes
+ awesome;
+
+ # Here we have a comment
+ if ('hello'): # hi there
+ in_more
+
+ same_level
+ if ['dude', 'dudess'].horsie(): first; second # both inside one_liner
+ 1
+
+ back_down
+
+last_statement
+
+hello = 1.1(20);
+
+# subscription
+a[1] = b[2];
+
+# simple slicing
+c[1:1] = d[2:2];
+
+# simple slicing
+e[1:1, 2:2] = f[3:3, 4:4];
+##### EXP #####
+*** SUCCESS ***
+
+hello
+def dude():
+ yes
+ awesome;
+
+ # Here we have a comment
+ def realy_awesome(): # hi there
+ in_more
+
+ same_level
+ def one_liner(): first; second # both inside one_liner
+
+ back_down
+
+last_statement
+
+# dude, this is a comment
+ # some more
+hello
+if 1:
+ yes
+ awesome;
+
+ # Here we have a comment
+ if ('hello'): # hi there
+ in_more
+
+ same_level
+ if ['dude', 'dudess'].horsie(): first; second # both inside one_liner
+ 1
+
+ back_down
+
+last_statement
+
+hello = 1.1(20);
+
+# subscription
+a[1] = b[2];
+
+# simple slicing
+c[1:1] = d[2:2];
+
+# simple slicing
+e[1:1, 2:2] = f[3:3, 4:4];
+***
+STMT: hello
+STMT: def dude():
+ yes
+ awesome;
+
+ # Here we have a comment
+ def realy_awesome(): # hi there
+ in_more
+
+ same_level
+ def one_liner(): first; second # both inside one_liner
+
+ back_down
+
+STMT: yes
+STMT: awesome;
+
+ # Here we have a comment
+STMT: def realy_awesome(): # hi there
+ in_more
+
+ same_level
+ def one_liner(): first; second # both inside one_liner
+
+STMT: in_more
+
+STMT: same_level
+STMT: def one_liner(): first; second # both inside one_liner
+
+STMT: back_down
+
+STMT: last_statement
+
+# dude, this is a comment
+ # some more
+STMT: hello
+STMT: if 1:
+ yes
+ awesome;
+
+ # Here we have a comment
+ if ('hello'): # hi there
+ in_more
+
+ same_level
+ if ['dude', 'dudess'].horsie(): first; second # both inside one_liner
+ 1
+
+ back_down
+
+STMT: yes
+STMT: awesome;
+
+ # Here we have a comment
+STMT: if ('hello'): # hi there
+ in_more
+
+ same_level
+ if ['dude', 'dudess'].horsie(): first; second # both inside one_liner
+ 1
+
+STMT: in_more
+
+STMT: same_level
+STMT: if ['dude', 'dudess'].horsie(): first; second # both inside one_liner
+STMT: 1
+
+STMT: back_down
+
+STMT: last_statement
+
+STMT: hello = 1.1(20);
+
+# subscription
+STMT: a[1] = b[2];
+
+# simple slicing
+STMT: c[1:1] = d[2:2];
+
+# simple slicing
+STMT: e[1:1, 2:2] = f[3:3, 4:4];
+TARGET SUBSCRIPTION: [1]
+TARGET SIMPLE SLICING: [1:1]
+TARGET EXTENDED SLICING: [1:1, 2:2]
+PRIMARY SUBSCRIPTION: [2]
+PRIMARY SIMPLE SLICING: [2:2]
+PRIMARY EXTENDED SLICING: [3:3, 4:4]
+*** SUCCESS ***
diff --git a/test/generate2.lm b/test/generate2.lm
new file mode 100644
index 00000000..1637044a
--- /dev/null
+++ b/test/generate2.lm
@@ -0,0 +1,223 @@
+context generate
+ struct open_item
+ type: str
+ num: int
+
+ list_el el
+ end
+
+ open_item new_open_item( type: str num: int )
+ {
+ OI: open_item = new open_item
+ OI->type = type
+ OI->num = num
+ return OI
+ }
+
+ OpenStack: list<open_item>
+
+ lex
+ token stray_close //
+
+ token ocurly /'{'+/
+ {
+ input->pull( match_length )
+
+ OI: open_item = new_open_item( '{' match_length )
+ OpenStack->push( OI )
+ i: int = 0
+ while ( i < match_length ) {
+ input->push( make_token( typeid<ocurly> '{' ) )
+ i = i + 1
+ }
+ }
+
+ token ccurly1 //
+ token ccurly2 //
+ token ccurly3 //
+ token missing_curly //
+
+ token tmp1 /'}'+/
+ {
+ if OpenStack->length > 0 && OpenStack->top->type == '{' {
+ length: int = 3
+ if ( length > match_length )
+ length = match_length
+
+ Top: open_item = OpenStack->pop()
+ if ( length > Top->num )
+ length = Top->num
+
+ if ( length == 1 )
+ input->push( make_token( typeid<ccurly1> input->pull( 1 ) ) )
+ else if ( length == 2 )
+ input->push( make_token( typeid<ccurly2> input->pull( 2 ) ) )
+ else if ( length == 3 )
+ input->push( make_token( typeid<ccurly3> input->pull( 3 ) ) )
+
+ Top->num = Top->num - length
+
+ if ( Top->num > 0 )
+ OpenStack->push( Top )
+ }
+ else {
+ input->push( make_token( typeid<stray_close> input->pull( match_length ) ) )
+ }
+ }
+
+ token osquare /'['+/
+ {
+ input->pull( match_length )
+ OI: open_item = new_open_item( '[' match_length )
+ OpenStack->push( OI )
+ i: int = 0
+ while ( i < match_length ) {
+ input->push( make_token( typeid<osquare> '[' ) )
+ i = i + 1
+ }
+ }
+
+ token csquare1 //
+ token csquare2 //
+ token missing_square //
+
+ token tmp2 /']'+/
+ {
+ if OpenStack->length > 0 && OpenStack->top->type == '[' {
+ length: int = 2
+ if ( length > match_length )
+ length = match_length
+
+ Top: open_item = OpenStack->pop()
+ if ( length > Top->num )
+ length = Top->num
+
+ if ( length == 1 )
+ input->push( make_token( typeid<csquare1> input->pull( 1 ) ) )
+ else if ( length == 2 )
+ input->push( make_token( typeid<csquare2> input->pull( 2 ) ) )
+
+ Top->num = Top->num - length
+
+ if ( Top->num > 0 )
+ OpenStack->push( Top )
+ }
+ else {
+ input->push( make_token( typeid<stray_close> input->pull( match_length ) ) )
+ }
+ }
+
+ literal `|
+ token char /any/
+
+ preeof {
+ while ( OpenStack->length > 0 ) {
+ Top: open_item = OpenStack->pop()
+ i: int
+ if ( Top->type == '{' ) {
+ i = 0
+ while ( i < Top->num ) {
+ input->push( make_token( typeid<missing_curly> '}' ) )
+ i = i + 1
+ }
+ }
+ else if ( Top->type == '[' ) {
+ i = 0
+ while ( i < Top->num ) {
+ input->push( make_token( typeid<missing_square> ']' ) )
+ i = i + 1
+ }
+ }
+ }
+ }
+ end
+
+ #
+ # Internal Links
+ #
+
+
+ lex
+ literal `http:
+ literal `ftp:
+ literal `mailto:
+ end
+
+ def el_prefix
+ [`http:]
+ | [`ftp:]
+ | [`mailto:]
+
+ def external_link
+ [osquare item* csquare1]
+
+ def internal_link
+ [osquare osquare item* csquare2]
+
+ def unclosed_square
+ [osquare item* missing_square]
+
+ #
+ # Templates
+ #
+
+ def sing_template
+ [ocurly item* ccurly1]
+
+ def template
+ [ocurly ocurly item* ccurly2]
+
+ def parameter
+ [ocurly ocurly ocurly item* ccurly3]
+
+ def unclosed_curly
+ [ocurly item* missing_curly]
+
+ #
+ # Template Parameters
+ #
+
+
+ def U1 []
+ def U2 []
+ def U3 []
+
+ def item
+ [external_link]
+ | [internal_link]
+ | [unclosed_curly]
+ | [sing_template]
+ | [template]
+ | [parameter]
+ | [unclosed_curly]
+ | [stray_close]
+ | [osquare]
+ | [`|]
+ | [char]
+
+ def start
+ [item*]
+
+end # generate
+
+Generate: generate = new generate
+
+Generate->OpenStack = new list<generate::open_item>
+Sentinal: generate::open_item = new_open_item( '** SENTINAL **' 1 )
+Generate->OpenStack->push( Sentinal )
+
+parse S: generate::start(Generate)[stdin]
+
+if S {
+ for I: generate::external_link in S
+ print( 'EXTERNAL LINK: ' I '\n' )
+
+ for I: generate::internal_link in S
+ print( 'INTERNAL LINK: ' I '\n' )
+}
+##### IN #####
+[external]
+[[internal]]
+##### EXP #####
+EXTERNAL LINK: [external]
+INTERNAL LINK: [[internal]]
diff --git a/test/lookup1.lm b/test/lookup1.lm
new file mode 100644
index 00000000..38902582
--- /dev/null
+++ b/test/lookup1.lm
@@ -0,0 +1,2594 @@
+
+context lookup
+ struct list_lang_object_el
+ Obj: lang_object
+ list_el el
+ end
+
+ alias list_lang_object
+ list<list_lang_object_el>
+
+ alias list_declaration_data
+ list<declaration_data>
+
+ alias list_declarator_data
+ list<declarator_data>
+
+ struct list_int_el
+ Int: int
+ list_el el
+ end
+
+ alias list_int
+ list<list_int_el>
+
+ struct map_list_lang_object_el
+ List: list_lang_object
+ map_el<str> el
+ end
+
+ alias map_list_lang_object
+ map<str map_list_lang_object_el>
+
+ #
+ # Data types for global data.
+ #
+
+ # Language objects.
+ struct lang_object
+ typeId: int
+ name: str
+
+ # If the object is a typedef, this points to the real object.
+ typedefOf: lang_object
+
+ objectMap: map_list_lang_object
+ inherited: list_lang_object
+ lookupParent: lang_object
+ specializationOf: lang_object
+ end
+
+ # This structure is used to keep track of information necessary to make a
+ # declaration. While parsing a declaration it records the declaration's
+ # attributes.
+ struct declaration_data
+ isTypedef: int
+ isFriend: int
+ isTemplate: int
+
+ typeObj: lang_object
+
+ list_el el
+ end
+
+ struct declarator_data
+ qualObj: lang_object
+ pdcScope: lang_object
+ lookupObj: lang_object
+
+ list_el el
+ end
+
+ # Constants for language object types.
+ NamespaceType: int
+ ClassType: int
+ TemplateClassType: int
+ EnumType: int
+ IdType: int
+ TypedefType: int
+ TemplateIdType: int
+
+ #
+ # Global data declarations
+ #
+
+ # Object stacks.
+ curNamespace: list_lang_object
+ declNs: list_lang_object
+ lookupNs: list_lang_object
+ qualNs: list_lang_object
+ templateParamNs: list_lang_object
+
+ # Declaration, declarator data.
+ declarationData: list_declaration_data
+ declaratorData: list_declarator_data
+
+ # Template declarations
+ templDecl: list_int
+
+ # Root namespace object
+ rootNamespace: lang_object
+
+ #
+ # Identifier lookup.
+ #
+
+ # Lookup the token in the members of an object.
+ lang_object lookupInObject( obj: lang_object name: str )
+ {
+ # LOG print( ' looking in ', obj->name, '\n' )
+
+ ol: map_list_lang_object_el = obj->objectMap->find( name )
+ if ol {
+ # LOG print( ' * found an object: ', ol.head, '\n' )
+ return ol->List->head->Obj
+ }
+
+ return nil
+ }
+
+ # Lookup in an object and all the objects beneath it in the inheritance
+ # tree.
+ lang_object lookupWithInheritance( obj: lang_object name: str )
+ {
+ found: lang_object = lookupInObject( obj name )
+ if found
+ return found
+
+ localObjInherited: list_lang_object = obj->inherited
+ II: list_lang_object_el = localObjInherited->head
+ while II {
+ inh: lang_object = II->Obj
+
+ # First check if the inherited object is the one we are after.
+ if inh->name == name && inh->typeId == ClassType {
+ # LOG print( ' * found a class name\n' )
+ return inh
+ }
+
+ # Otherwise look inside the inherited object.
+ found = lookupWithInheritance( inh name )
+ if found
+ return found
+
+ II = II->next
+ }
+
+ return nil
+ }
+
+ lang_object unqualifiedLookup( name: str )
+ {
+ found: lang_object
+
+ # Start with the objects in the templateParamNs.
+ localTemplateParamNs: list_lang_object = templateParamNs
+ TemplParaObjIter: list_lang_object_el = localTemplateParamNs->tail
+ while ( TemplParaObjIter ) {
+ found = lookupWithInheritance( TemplParaObjIter->Obj name )
+ if found
+ break
+ TemplParaObjIter = TemplParaObjIter->prev
+ }
+
+ if !found {
+ # Iterator over the objects starting at the head of the lookup stack
+ # and going up through the lookup parents.
+ lookupIn: lang_object = lookupNs->tail->Obj
+ while lookupIn {
+ found = lookupWithInheritance( lookupIn name )
+ if found
+ break
+ lookupIn = lookupIn->lookupParent
+ }
+ }
+
+ return found
+ }
+
+ # The C++ scanner.
+ lex
+ rl fract_const / digit* '.' digit+ | digit+ '.' /
+ rl exponent / [eE] [+\-]? digit+ /
+ rl float_suffix / [flFL] /
+
+ # Single and double literals.
+ token TK_SingleLit /( 'L'? "'" ( [^'\\\n] | '\\' any )* "'" )/
+ token TK_DoubleLit /( 'L'? '"' ( [^"\\\n] | '\\' any )* '"' )/
+
+ literal `extern `namespace `friend `typedef `auto `register
+ `static `mutable `inline `virtual `explicit `const
+ `volatile `restrict `class `struct `union `template
+ `private `protected `public `using `void `char
+ `wchar_t `bool `int `float `double `short `long
+ `signed `unsigned `enum `new `delete `operator
+ `typename `export `throw `try `catch `sizeof
+ `dynamic_cast `static_cast `reinterpret_cast `const_cast
+ `typeid `this `true `false `switch `case `default
+ `if `else `while `do `for `break `continue
+ `return `goto
+
+ # Extensions
+ literal `__typeof `__is_pod `__is_empty
+
+ literal `{ `} `; `, `= `( `) `: `& `* `[ `] `~ `+ `-
+ `/ `< `> `| `^ `% `! `? `.
+
+ literal `:: `== `!= `&& `|| `*= `/= `%= `+= `-= `&=
+ `^= `|= `++ `-- `-> `->* `.* `... `<<= `>>=
+
+ # Token translation targets.
+ def unknown_id [lookup_id]
+ def class_id [lookup_id]
+ def namespace_id [lookup_id]
+ def templ_class_id [lookup_id]
+ def enum_id [lookup_id]
+ def typedef_id [lookup_id]
+ def identifier [lookup_id]
+ def template_id [lookup_id]
+
+ # Identifiers
+ token lookup_id
+ obj: lang_object
+ qualObj: lang_object
+
+ /( [a-zA-Z_] [a-zA-Z0-9_]* )/
+ {
+ name: str = match_text
+ found: lang_object = nil
+ qualObj: lang_object = nil
+ if qualNs->tail->Obj {
+ # LOG print( 'qualified lookup of ', name, '\n' )
+
+ # Transfer the qualification to the token and reset it.
+ qualObj = qualNs->tail->Obj
+ qualNs->tail->Obj = nil
+
+ # Lookup using the qualification.
+ found = lookupWithInheritance( qualObj name )
+ }
+ else {
+ # No qualification, full search.
+ # LOG print( 'unqualified lookup of ', name, '\n' )
+ found = unqualifiedLookup( name )
+ }
+
+ # If no match, return an Unknown ID
+ id: int = typeid<unknown_id>
+ if found
+ id = found->typeId
+
+ LookupId: lookup_id = make_token( typeid<lookup_id> input->pull(match_length) )
+ LookupId.obj = found
+ LookupId.qualObj = qualObj
+
+ input->push( make_tree( id LookupId ) )
+ }
+
+ # Floats.
+ token TK_Float /( fract_const exponent? float_suffix? |
+ digit+ exponent float_suffix? )/
+
+ # Integer decimal. Leading part buffered by float.
+ token TK_IntegerDecimal /( ( '0' | [1-9] [0-9]* ) [ulUL]{0,3} )/
+
+ # Integer octal. Leading part buffered by float.
+ token TK_IntegerOctal /( '0' [0-9]+ [ulUL]{0,2} )/
+
+ # Integer hex. Leading 0 buffered by float.
+ token TK_IntegerHex /( '0x' [0-9a-fA-F]+ [ulUL]{0,2} )/
+
+ # Preprocessor line.
+ ignore /'#' [^\n]* '\n'/
+
+ # Comments and whitespace.
+ ignore /( '/*' (any | '\n')* :>> '*/' )/
+ ignore /( '//' any* :> '\n' )/
+ ignore /( any - 33..126 )+/
+ end
+
+ #
+ # Support functions
+ #
+
+ typeId: int
+ name: str
+
+ # If the object is a typedef, this points to the real object.
+ typedefOf: lang_object
+
+ objectMap: map_list_lang_object
+ inherited: list_lang_object
+ lookupParent: lang_object
+ specializationOf: lang_object
+
+ lang_object createLangObject( typeId: int name: str lookupParent: lang_object )
+ {
+ Obj: lang_object = new lang_object
+
+ Obj->typeId = typeId
+ Obj->name = name
+ Obj->typedefOf = nil
+ Obj->objectMap = new map_list_lang_object
+ Obj->inherited = new list_lang_object
+ Obj->lookupParent = lookupParent
+
+ return Obj
+ }
+
+ # Building the language object tree.
+ int insertObject( definedIn: lang_object name: str obj: lang_object )
+ {
+ ol: map_list_lang_object_el = definedIn->objectMap->find( name )
+ if !ol {
+ # Element not in the map already
+ ol = new map_list_lang_object_el
+ ol->key = name
+ ol->List = new list_lang_object
+ definedIn->objectMap->insert( ol )
+ }
+ E: list_lang_object_el = new list_lang_object_el
+ E->Obj = obj
+ ol->List->push_tail( E )
+ }
+
+ lang_object findClass( inObj: lang_object lang_objectname: str )
+ {
+ ol: map_list_lang_object_el = inObj->objectMap->find( name )
+ if ol {
+ ObjIter: list_lang_object_el = ol->List->head
+ while ( ObjIter ) {
+ obj: lang_object = ObjIter->Obj
+ if obj->typeId == ClassType {
+ return obj
+ }
+ ObjIter = ObjIter->next
+ }
+ }
+ return nil
+ }
+
+ lang_object findTemplateClass( inObj: lang_object name: str )
+ {
+ ol: map_list_lang_object_el = inObj->objectMap->find( name )
+ if ol {
+ ObjIter: list_lang_object_el = ol->List->head
+ while ( ObjIter ) {
+ obj: lang_object = ObjIter->Obj
+ if obj->typeId == TemplateClassType
+ return obj
+ ObjIter = ObjIter->next
+ }
+ }
+ return nil
+ }
+
+ def root_qual_opt
+ []
+ | [`::]
+
+ def nested_name_specifier_opt
+ [nested_name_specifier_opt qualifying_name `:: designated_qualifying_name `::]
+ | [nested_name_specifier_opt qualifying_name `::]
+ | []
+
+ def nested_name_specifier
+ [nested_name_specifier designated_qualifying_name `::]
+ | [nested_name_specifier qualifying_name `::]
+ | [qualifying_name `::]
+
+ def qualifying_name
+ [class_name]
+ {
+ qualNs->tail->Obj = r1.lookupId.obj
+ }
+
+ | [namespace_id]
+ {
+ match r1 [Id: lookup_id]
+ qualNs->tail->Obj = Id.obj
+ }
+
+ | [typedef_id]
+ {
+ match r1 [Id: lookup_id]
+ qualNs->tail->Obj = Id.obj->typedefOf
+ }
+
+ def designated_qualifying_name
+ [`template any_id]
+ {
+ # FIXME: nulling qualNs is not the right thing to do here.
+ qualNs->tail->Obj = nil
+ }
+
+ | [`template any_id
+ templ_arg_open template_argument_list_opt templ_arg_close]
+ {
+ # FIXME: nulling qualNs is not the right thing to do here.
+ qualNs->tail->Obj = nil
+ }
+
+ #
+ # Id Expression
+ #
+
+ def id_expression
+ lookupId: lookup_id
+
+ [root_qual_opt nested_name_specifier_opt unknown_id]
+ {
+ lhs.lookupId = lookup_id in r3
+ }
+
+ | [root_qual_opt nested_name_specifier_opt identifier]
+ {
+ lhs.lookupId = lookup_id in r3
+ }
+
+ | [root_qual_opt nested_name_specifier_opt operator_function_id]
+ {
+ # Normally the token translation transfers the qualification. Since
+ # the operator_function_id does not end in a lookup we must do it ourselves.
+ qualObj: lang_object = qualNs->tail->Obj
+ qualNs->tail->Obj = nil
+
+ lhs.lookupId = construct lookup_id ["x"]
+ lhs.lookupId.data = '<operator_function_id>'
+ lhs.lookupId.qualObj = qualObj
+ }
+
+ | [root_qual_opt nested_name_specifier_opt conversion_function_id]
+ {
+ # Normally the token translation transfers the qualification. Since
+ # the operator_function_id does not } in a lookup we must do it ourselves.
+ qualObj: lang_object = qualNs->tail->Obj
+ qualNs->tail->Obj = nil
+
+ # Do we need qual reset here becauase operator_function_id does not do it?
+ lhs.lookupId = construct lookup_id ["x"]
+ lhs.lookupId.data = '<conversion_function_id>'
+ lhs.lookupId.qualObj = qualObj
+ }
+
+ | [root_qual_opt nested_name_specifier_opt `~ class_name]
+ {
+ lhs.lookupId = r4.lookupId
+ }
+
+ | [root_qual_opt nested_name_specifier_opt template_name]
+ {
+ lhs.lookupId = r3.lookupId
+ }
+
+ def template_name
+ lookupId: lookup_id
+
+ [template_id templ_arg_open template_argument_list_opt templ_arg_close]
+ {
+ lhs.lookupId = lookup_id in r1
+ }
+
+ | [template_id]
+ {
+ lhs.lookupId = lookup_id in r1
+ }
+
+
+ #
+ # Class Names
+ #
+
+ def class_name
+ lookupId: lookup_id
+
+ [class_id]
+ {
+ lhs.lookupId = lookup_id in r1
+ }
+
+ | [templ_class_id]
+ {
+ lhs.lookupId = lookup_id in r1
+ }
+
+ | [templ_class_id templ_arg_open template_argument_list_opt templ_arg_close]
+ {
+ # TODO: Look for a specialization.
+ lhs.lookupId = lookup_id in r1
+ }
+
+ def templ_arg_open
+ [`<]
+ {
+ E: list_lang_object_el = new list_lang_object_el
+ E->Obj = nil
+ qualNs->push_tail( E )
+ }
+
+ def templ_arg_close
+ [`>]
+ {
+ qualNs->pop_tail()
+ }
+
+ def declaration
+ [block_declaration] commit
+ | [function_definition] commit
+ | [template_declaration] commit
+ | [explicit_instantiation] commit
+ | [explicit_specialization] commit
+ | [linkage_specification] commit
+ | [namespace_definition] commit
+
+ #
+ # Declarations
+ #
+
+ def block_declaration
+ [simple_declaration]
+ | [using_declaration]
+ | [using_directive]
+
+ def simple_declaration
+ [declaration_start simple_declaration_forms declaration_end `;]
+
+ # Ordering is important for optimization. The form with the optional
+ # decl_specifier_sing should go second.
+ def simple_declaration_forms
+ [decl_specifier_mult_seq_opt decl_specifier_sing
+ decl_specifier_mult_seq_opt init_declarator_list_opt]
+
+ | [decl_specifier_mult_seq_opt init_declarator_list_opt]
+
+ def declaration_start
+ []
+ {
+ # LOG print( 'opening new declaration_data with templDecl: ', templDecl.tail, '\n' )
+ DD: declaration_data = new declaration_data
+ DD->isTypedef = 0
+ DD->isFriend = 0
+ DD->isTemplate = 0
+ declarationData->push_tail( DD )
+
+ # Transfer the template flag and reset it.
+ declarationData->tail->isTemplate = templDecl->tail->Int
+ IntEl: list_int_el = new list_int_el
+ IntEl->Int = 0
+ templDecl->push_tail( IntEl )
+ }
+
+ def declaration_end
+ []
+ {
+ # LOG print( 'closing declaration_data\n' )
+ declarationData->pop_tail()
+ templDecl->pop_tail()
+ }
+
+ def decl_specifier_sing
+ [type_specifier_sing]
+ {
+ # Store the object type of the declaration (if any) for use
+ # by typedefs.
+ declarationData->tail->typeObj = r1.lookupId.obj
+ }
+
+ def type_specifier_seq
+ lookupId: lookup_id
+
+ [type_specifier_mult_seq_opt type_specifier_sing type_specifier_mult_seq_opt]
+ {
+ lhs.lookupId = r2.lookupId
+ }
+
+ def type_specifier_sing
+ lookupId: lookup_id
+
+ [simple_type_specifier]
+ {
+ lhs.lookupId = r1.lookupId
+ }
+
+ | [class_specifier]
+ {
+ lhs.lookupId = construct lookup_id ["x"]
+ lhs.lookupId.data = '<class_specifier>'
+ }
+
+ | [enum_specifier]
+ {
+ lhs.lookupId = construct lookup_id ["x"]
+ lhs.lookupId.data = '<enum_specifier>'
+ }
+
+ | [elaborated_type_specifier]
+ {
+ lhs.lookupId = construct lookup_id ["x"]
+ lhs.lookupId.data = '<elaborated_type_specifier>'
+ }
+
+ # Type specifier sequence without enum specifier or class specifier.
+ def necs_type_specifier_seq
+ [type_specifier_mult_seq_opt necs_type_specifier_sing type_specifier_mult_seq_opt]
+
+ # Type specifier singular without enum specifier or class specifier.
+ def necs_type_specifier_sing
+ [simple_type_specifier]
+ | [elaborated_type_specifier]
+
+ def type_specifier_mult_seq_opt
+ [type_specifier_mult_seq_opt type_specifier_mult]
+ | []
+
+ def type_specifier_mult_seq
+ [type_specifier_mult_seq type_specifier_mult]
+ | [type_specifier_mult]
+
+ def simple_type_specifier
+ lookupId: lookup_id
+
+ [simple_type_specifier_name]
+ {
+ lhs.lookupId = r1.lookupId
+ }
+
+ | [simple_type_specifier_kw_seq]
+ {
+ lhs.lookupId = construct lookup_id ["x"]
+ lhs.lookupId.data = '<simple_type_specifier_kw_seq>'
+ }
+
+ | [`typename root_qual_opt nested_name_specifier type_name]
+ {
+ lhs.lookupId = r4.lookupId
+ }
+
+ | [`typename root_qual_opt nested_name_specifier identifier]
+ {
+ lhs.lookupId = lookup_id in r4
+ }
+
+ | [`typename root_qual_opt nested_name_specifier unknown_id]
+ {
+ lhs.lookupId = lookup_id in r4
+ }
+
+ # Extension.
+ | [`__typeof `( expression `)]
+ {
+ lhs.lookupId = construct lookup_id ["x"]
+ lhs.lookupId.data = '<simple_type_specifier_kw_seq>'
+ }
+
+ def simple_type_specifier_name
+ lookupId: lookup_id
+
+ [qual_type_name]
+ {
+ lhs.lookupId = r1.lookupId
+ }
+
+ def simple_type_specifier_kw_seq
+ [simple_type_specifier_kw_seq simple_type_specifier_kw]
+ | [simple_type_specifier_kw]
+
+ def simple_type_specifier_kw
+ [`void]
+ | [`char]
+ | [`wchar_t]
+ | [`bool]
+ | [`int]
+ | [`float]
+ | [`double]
+ | [`short]
+ | [`long]
+ | [`signed]
+ | [`unsigned]
+
+ def qual_type_name
+ lookupId: lookup_id
+
+ [root_qual_opt nested_name_specifier_opt type_name]
+ {
+ lhs.lookupId = r3.lookupId
+ }
+
+ def type_name
+ lookupId: lookup_id
+
+ [class_name]
+ {
+ lhs.lookupId = r1.lookupId
+ }
+
+ | [enum_id]
+ {
+ lhs.lookupId = lookup_id in r1
+ }
+
+ | [typedef_id]
+ {
+ lhs.lookupId = lookup_id in r1
+ }
+
+ # NOTE: the typename case is moved to simple type specifier
+ # to take advantage of its conflict resolution.
+ def elaborated_type_specifier
+ [class_key nested_name_specifier_opt class_head_name]
+ {
+ Id: lookup_id = lookup_id in r3
+ name: str = Id.data
+
+ # Get the ns the class is declared in.
+ parentObj: lang_object = declNs->tail->Obj
+ if Id.qualObj
+ parentObj = Id.qualObj
+
+ # Look for the class in the given scope.
+ declaredClass: lang_object = findClass( parentObj name )
+ if !declaredClass
+ declaredClass = findTemplateClass( parentObj name )
+
+ if !declaredClass {
+ # LOG print( 'creating new class: ', name, '\n' )
+
+ # Class does not exist in the parent scope, create it.
+ nsType: int = declaredClassType()
+
+ declaredClass = createLangObject( nsType name lookupNs->tail->Obj )
+
+ # FIXME: handle friends. Make the class visible only if we are NOT
+ # in a friend declaration. The new class object is necessary to
+ # properly process the body of the class.
+ if declarationData->tail->isFriend == 0
+ insertObject( parentObj name declaredClass )
+ }
+ }
+
+ # TODO: Lookup type specialization.
+ | [class_key nested_name_specifier_opt templ_class_id
+ templ_arg_open template_argument_list_opt templ_arg_close]
+
+ | [`enum nested_name_specifier_opt enum_head_name]
+ {
+ # TODO: should look for existing enums of the same name.
+ Id: lookup_id = lookup_id in r3
+ # LOG print( 'creating enumeration ' Id.data '\n' )
+ enum: lang_object = createLangObject( EnumType Id.data lookupNs->tail->Obj )
+ insertObject( declNs->tail->Obj Id.data enum )
+ }
+
+ def decl_specifier_mult_seq_opt
+ [decl_specifier_mult_seq_opt decl_specifier_mult]
+ | []
+
+ def decl_specifier_mult_seq
+ [decl_specifier_mult_seq decl_specifier_mult]
+ | [decl_specifier_mult]
+
+ def decl_specifier_mult
+ [type_specifier_mult]
+ | [storage_class_specifier]
+ | [function_specifier]
+
+ | [`friend]
+ {
+ declarationData->tail->isFriend = 1
+ }
+
+ | [`typedef]
+ {
+ declarationData->tail->isTypedef = 1
+ }
+
+ def storage_class_specifier
+ [`auto]
+ | [`register]
+ | [`static]
+ | [`extern]
+ | [`mutable]
+
+ def function_specifier
+ [`inline]
+ | [`virtual]
+ | [`explicit]
+
+ def type_specifier_mult
+ [cv_qualifier]
+
+ def cv_qualifier
+ [`const]
+ | [`volatile]
+ | [`restrict]
+
+ def cv_qualifier_rep
+ [cv_qualifier_rep cv_qualifier]
+ | []
+
+ def namespace_definition
+ [named_namespace_definition]
+ | [unnamed_namespace_definition]
+
+ def named_namespace_definition
+ [original_namespace_definition]
+ | [extension_namespace_definition]
+
+ #
+ # Enumerations
+ #
+
+ def enum_specifier
+ [`enum nested_name_specifier_opt
+ enum_head_name `{ enumerator_list_opt `}]
+ {
+ # TODO: should look for existing enums of the same name.
+ Id: lookup_id = lookup_id in r3
+ # LOG print( 'creating enumeration ' Id.data '\n' )
+ enum: lang_object = createLangObject( EnumType Id.data lookupNs->tail->Obj )
+ insertObject( declNs->tail->Obj Id.data enum )
+ }
+
+ | [`enum `{ enumerator_list_opt `}]
+
+ def enum_head_name
+ [class_id]
+ | [templ_class_id]
+ | [namespace_id]
+ | [typedef_id]
+ | [enum_id]
+ | [identifier]
+ | [template_id]
+ | [unknown_id]
+
+ def enumerator_list_opt
+ [enumerator_list]
+ | [enumerator_list `,]
+ | []
+
+ def enumerator_list
+ [enumerator_list `, enumerator_definition]
+ | [enumerator_definition]
+
+ def enumerator_definition
+ [enumerator_id]
+ {
+ Id: lookup_id = lookup_id in r1
+ enumId: lang_object = createLangObject( IdType Id.data lookupNs->tail->Obj )
+ insertObject( declNs->tail->Obj Id.data enumId )
+ }
+
+ | [enumerator_id `= constant_expression]
+ {
+ Id: lookup_id = lookup_id in r1
+ enumId: lang_object = createLangObject( IdType Id.data lookupNs->tail->Obj )
+ insertObject( declNs->tail->Obj Id.data enumId )
+ }
+
+ def enumerator_id
+ [namespace_id]
+ | [typedef_id]
+ | [enum_id]
+ | [class_id]
+ | [templ_class_id]
+ | [template_id]
+ | [identifier]
+ | [unknown_id]
+
+ #
+ # Declarators
+ #
+
+ def init_declarator_list_opt
+ [init_declarator_list]
+ | []
+
+ def init_declarator_list
+ [init_declarator_list `, init_declarator]
+ | [init_declarator]
+
+ def init_declarator
+ [declarator initializer_opt]
+
+ def initializer_opt
+ [`= initializer_clause]
+ | [`( expression `)]
+ | []
+
+ def initializer_clause
+ [assignment_expression]
+ | [`{ initializer_list `}]
+ | [`{ initializer_list `, `}]
+ | [`{ `}]
+
+ def initializer_list
+ [initializer_list `, initializer_clause]
+ | [initializer_clause]
+
+ #
+ # Expressions
+ #
+
+ def expression
+ [expression `, assignment_expression]
+ | [assignment_expression]
+
+ def expression_opt
+ [expression]
+ | []
+
+ def constant_expression
+ [conditional_expression]
+
+ def constant_expression_opt
+ [constant_expression]
+ | []
+
+ def assignment_expression
+ [conditional_expression]
+ | [logical_or_expression assignment_op assignment_expression]
+ | [throw_expression]
+
+ def assignment_op
+ [`=]
+ | [`*=]
+ | [`/=]
+ | [`%=]
+ | [`+=]
+ | [`-=]
+ | [`>>=]
+ | [`<<=]
+ | [`&=]
+ | [`^=]
+ | [`|=]
+
+ def conditional_expression
+ [logical_or_expression]
+ | [logical_or_expression `? expression `: assignment_expression]
+
+ def logical_or_expression
+ [logical_or_expression `|| logical_and_expression]
+ | [logical_and_expression]
+
+ def logical_and_expression
+ [logical_and_expression `&& inclusive_or_expression]
+ | [inclusive_or_expression]
+
+ def inclusive_or_expression
+ [inclusive_or_expression `| exclusive_or_expression]
+ | [exclusive_or_expression]
+
+ def exclusive_or_expression
+ [exclusive_or_expression `^ and_expression]
+ | [and_expression]
+
+ def and_expression
+ [and_expression `& equality_expression]
+ | [equality_expression]
+
+ def equality_expression
+ [equality_expression `== relational_expression]
+ | [equality_expression `!= relational_expression]
+ | [relational_expression]
+
+ def relational_expression
+ [relational_expression `< shift_expression]
+ | [relational_expression `> shift_expression]
+ | [relational_expression lt_eq shift_expression]
+ | [relational_expression gt_eq shift_expression]
+ | [shift_expression]
+
+ def shift_expression
+ [shift_expression shift_left additive_expression]
+ | [shift_expression shift_right additive_expression]
+ | [additive_expression]
+
+ def additive_expression
+ [additive_expression `+ multiplicative_expression]
+ | [additive_expression `- multiplicative_expression]
+ | [multiplicative_expression]
+
+ def multiplicative_expression
+ [multiplicative_expression `* pm_expression]
+ | [multiplicative_expression `/ pm_expression]
+ | [multiplicative_expression `% pm_expression]
+ | [pm_expression]
+
+ def pm_expression
+ [pm_expression `->* cast_expression]
+ | [pm_expression `.* cast_expression]
+ | [cast_expression]
+
+ def cast_expression
+ [unary_expression]
+ | [`( type_id `) cast_expression]
+
+ def delete_expression
+ [root_qual_opt `delete cast_expression]
+ | [root_qual_opt `delete `[ `] cast_expression]
+
+ def new_initializer_opt
+ [new_initializer]
+ | []
+
+ def new_initializer
+ [`( expression_opt `)]
+
+ def direct_new_declarator
+ [`[ expression `]]
+ | [direct_new_declarator `[ constant_expression `]]
+
+ def new_declarator_opt
+ [new_declarator]
+ | []
+
+ def new_declarator
+ [direct_new_declarator]
+ | [ptr_operator_seq direct_new_declarator]
+ | [ptr_operator_seq]
+
+ def new_type_id
+ [necs_type_specifier_seq new_declarator_opt]
+
+ def new_placement
+ [`( expression `)]
+
+ def new_expression
+ [root_qual_opt `new new_type_id new_initializer_opt]
+ | [root_qual_opt `new new_placement new_type_id new_initializer_opt]
+ | [root_qual_opt `new `( type_id `) new_initializer_opt]
+ | [root_qual_opt `new new_placement `( type_id `) new_initializer_opt]
+
+ def unary_operator
+ [`*]
+ | [`&]
+ | [`+]
+ | [`-]
+ | [`!]
+ | [`~]
+
+ def unary_expression
+ [postfix_expression]
+ | [`++ cast_expression]
+ | [`-- cast_expression]
+ | [unary_operator cast_expression]
+ | [`sizeof `( type_id `)]
+ | [`sizeof unary_expression]
+ | [new_expression]
+ | [delete_expression]
+
+ def function_style_type_conv
+ [simple_type_specifier]
+
+
+ def postfix_expression
+ [primary_expression]
+ | [postfix_expression `[ expression `]]
+ | [postfix_expression `( expression_opt `)]
+ | [function_style_type_conv `( expression_opt `)]
+ | [member_request_expr dot_arrow id_expression]
+ | [member_request_expr dot_arrow pseudo_destructor_call]
+ | [postfix_expression `++]
+ | [postfix_expression `--]
+ | [`dynamic_cast templ_arg_open type_id templ_arg_close `( expression `)]
+ | [`static_cast templ_arg_open type_id templ_arg_close `( expression `)]
+ | [`reinterpret_cast templ_arg_open type_id templ_arg_close `( expression `)]
+ | [`const_cast templ_arg_open type_id templ_arg_close `( expression `)]
+ | [`typeid `( expression `)]
+ | [`typeid `( type_id `)]
+
+ def pseudo_destructor_call
+ [root_qual_opt nested_name_specifier_opt `~ pdc_type_name]
+
+ def primary_expression
+ [expr_lit]
+ | [`this]
+ | [`( expression `)]
+ | [id_expression]
+ # GNU extensions
+ | [`( `{ statement_rep `} `)]
+ | [`__is_pod `( type_id `)]
+ | [`__is_empty `( type_id `)]
+
+ def expr_lit
+ [TK_IntegerDecimal]
+ | [TK_IntegerOctal]
+ | [TK_IntegerHex]
+ | [TK_SingleLit]
+ | [TK_Float]
+ | [double_lit_list]
+ | [`true]
+ | [`false]
+
+ def double_lit_list
+ [TK_DoubleLit double_lit_list]
+ | [TK_DoubleLit]
+
+ def member_request_expr
+ [postfix_expression]
+ # {
+ # # FIXME: If no proper type is found, we must fail.
+ # # LOG print( 'setting member request scope\n' )
+ # # qualNs.set( $1->type != 0 ? $1->type->getObject() : 0 );
+ # }
+
+ def dot_arrow
+ [`->]
+ | [`.]
+
+ def pdc_type_name
+ [enum_id]
+ | [typedef_id]
+
+ #
+ # Statements
+ #
+
+ def statement_rep
+ [statement_rep statement]
+ | []
+
+ def statement
+ [declaration_statement]
+ | [labeled_statement]
+ | [expression_statement]
+ | [compound_statement]
+ | [selection_statement]
+ | [iteration_statement]
+ | [jump_statement]
+ | [try_block]
+
+ def labeled_statement
+ [label_id `: statement]
+ | [`case constant_expression `: statement]
+ | [`default `: statement]
+
+ def label_id
+ [unknown_id]
+ | [identifier]
+ | [class_id]
+ | [templ_class_id]
+ | [namespace_id]
+ | [typedef_id]
+ | [enum_id]
+ | [template_id]
+
+ def compound_statement
+ [`{ compound_begin statement_rep compound_end `}]
+
+ def compound_begin
+ []
+ {
+ newCompound: lang_object = createLangObject( 0 '<compound_begin>' lookupNs->tail->Obj )
+ E1: list_lang_object_el = new list_lang_object_el
+ E1->Obj = newCompound
+ lookupNs->push_tail( E1 )
+
+ E2: list_lang_object_el = new list_lang_object_el
+ E2->Obj = newCompound
+ declNs->push_tail( E2 )
+ # LOG print( 'opening <compound>\n' )
+ }
+
+ def compound_end
+ []
+ {
+ lookupNs->pop_tail()
+ declNs->pop_tail()
+ # LOG print( 'closing <compound>\n' )
+ }
+
+ def selection_statement
+ [`if `( condition `) statement elseif_clauses else_clause]
+ | [`switch `( condition `) statement]
+
+ def elseif_clauses
+ [elseif_clauses `else `if `( condition `) statement]
+ | []
+
+ def else_clause
+ [`else statement]
+ | []
+
+ def iteration_statement
+ [`while `( condition `) statement]
+ | [`do statement `while `( expression `) `;]
+ | [`for `( for_init_statement condition_opt `; expression_opt `) statement]
+
+ def jump_statement
+ [`break `;]
+ | [`continue `;]
+ | [`return expression_opt `;]
+ | [`goto any_id `;]
+
+ def any_id
+ [unknown_id]
+ | [class_id]
+ | [namespace_id]
+ | [templ_class_id]
+ | [enum_id]
+ | [typedef_id]
+ | [identifier]
+ | [template_id]
+
+
+ def for_init_statement
+ [expression_statement]
+ | [stmt_block_declaration_forms `;]
+
+ def condition
+ [expression]
+ | [type_specifier_seq declarator `= assignment_expression]
+
+ def condition_opt
+ [condition]
+ | []
+
+ def expression_statement
+ [expression `;]
+ | [`;]
+
+ def declaration_statement
+ [stmt_block_declaration]
+
+ def stmt_block_declaration
+ [declaration_start stmt_block_declaration_forms declaration_end `;]
+ | [using_declaration]
+ | [using_directive]
+
+ def stmt_block_declaration_forms
+ [decl_specifier_mult_seq_opt decl_specifier_sing decl_specifier_mult_seq_opt
+ init_declarator_list_opt]
+ | [decl_specifier_mult_seq init_declarator_list_opt]
+
+ #
+ # Declarators
+ #
+
+ def declarator
+ lookupObj: lang_object
+
+ [ptr_operator_seq_opt declarator_id decl_array_or_param_rep declarator_end]
+ {
+ lhs.lookupObj = r4.lookupObj
+ }
+
+ | [ptr_operator_seq_opt `( sub_declarator `) decl_array_or_param_rep declarator_end]
+ {
+ lhs.lookupObj = r6.lookupObj
+ }
+
+ def sub_declarator
+ [ptr_operator_seq declarator_id decl_array_or_param_rep]
+ | [ptr_operator_seq `( sub_declarator `) decl_array_or_param_rep]
+ | [`( sub_declarator `) decl_array_or_param_rep]
+ | [declarator_id decl_array_or_param_rep]
+
+ def decl_array_or_param_rep
+ [decl_array_or_param_rep decl_array_or_param]
+ | []
+
+ def decl_array_or_param
+ [`[ constant_expression_opt `]]
+ | [`( parameter_declaration_clause `) cv_qualifier_rep exception_specification_opt]
+
+ def declarator_id
+ [declarator_id_forms]
+ {
+ name: str = r1.lookupId.data
+ qualObj: lang_object = r1.lookupId.qualObj
+
+ parentObj: lang_object = declNs->tail->Obj
+ if qualObj {
+ parentObj = qualObj
+ }
+
+ # Decide if we are declaring a constructor/destructor.
+ isConstructor: bool
+ if parentObj == r1.lookupId.obj {
+ isConstructor = true
+ # LOG print( 'making declarator ' name ' a constructor/destructor\n' )
+ }
+
+ if parentObj->specializationOf &&
+ parentObj->specializationOf == r1.lookupId.obj
+ {
+ isConstructor = true
+ # LOG print( 'making declarator ' name ' a constructor/destructor\n' )
+ }
+
+ obj: lang_object = nil
+ if name && !isConstructor && declarationData->tail->isFriend == 0 {
+ if declarationData->tail->isTypedef {
+ obj = createLangObject( TypedefType name lookupNs->tail->Obj )
+ obj->typedefOf = declarationData->tail->typeObj
+ insertObject( parentObj name obj )
+
+ # LOG print( 'making declarator ' name ' a typedef\n' )
+ }
+ else {
+ if !qualObj {
+ if declarationData->tail->isTemplate {
+ # If in a template declaration and the name is not qualified then
+ # create the template id.
+ obj = createLangObject( TemplateIdType name lookupNs->tail->Obj )
+ #object->objType = declarationData.tail.type
+ insertObject( declNs->tail->Obj name obj )
+
+ # LOG print( 'making declarator ' name ' a template id\n' )
+ }
+ else {
+ obj = createLangObject( IdType name lookupNs->tail->Obj )
+ #object->objType = declarationData.tail().type;
+ insertObject( declNs->tail->Obj name obj )
+
+ # LOG print( 'making declarator ' name ' an id\n' )
+ }
+ }
+ }
+ }
+
+
+ DD: declarator_data = new declarator_data
+ DD->qualObj = qualObj
+ DD->pdcScope = nil
+ DD->lookupObj = lookupNs->tail->Obj
+
+ declaratorData->push_tail( DD )
+
+ # If the declarator is qualified, push the qualification to the lookup
+ # stack. Also save it in the declarator data so it can be passed to a
+ # function body if needed.
+ if qualObj {
+ E: list_lang_object_el = new list_lang_object_el
+ E->Obj = qualObj
+ lookupNs->push_tail( E )
+ declaratorData->tail->lookupObj = qualObj
+ }
+
+ # LOG print( 'reduced declarator_id: ' name '\n' )
+ }
+
+ # Undoes the setup done by declarator_id and pdc_start.
+ def declarator_end
+ lookupObj: lang_object
+
+ []
+ {
+ # Get the lookupObject from the scope and pass it up. If we are about to
+ # parse a function body it will be needed.
+ lhs.lookupObj = declaratorData->tail->lookupObj
+
+ pdcScope: lang_object = declaratorData->tail->pdcScope
+ qualObj: lang_object = declaratorData->tail->qualObj
+
+ declaratorData->pop_tail()
+
+ if pdcScope {
+ # LOG print( 'closing <pdc_scope>\n' )
+ lookupNs->pop_tail()
+ declNs->pop_tail()
+ }
+
+ if qualObj {
+ # LOG print( 'popping lookupNs\n' )
+ lookupNs->pop_tail()
+ }
+ }
+
+ def declarator_id_forms
+ lookupId: lookup_id
+
+ [id_expression]
+ {
+ lhs.lookupId = r1.lookupId
+ }
+
+ | [root_qual_opt nested_name_specifier_opt type_name]
+ {
+ lhs.lookupId = r3.lookupId
+ }
+
+ | [root_qual_opt nested_name_specifier_opt `~ class_id]
+ {
+ lhs.lookupId = lookup_id in r4
+ }
+
+ | [root_qual_opt nested_name_specifier_opt `~ templ_class_id]
+ {
+ lhs.lookupId = lookup_id in r4
+ }
+ | [root_qual_opt nested_name_specifier_opt `~ unknown_id]
+ {
+ lhs.lookupId = lookup_id in r4
+ }
+
+ def type_id
+ lookupId: lookup_id
+
+ [type_specifier_seq abstract_declarator_opt]
+ {
+ lhs.lookupId = r1.lookupId
+ }
+
+ def abstract_declarator_opt
+ [abstract_declarator]
+ | []
+
+ def abstract_declarator
+ [ptr_operator_seq abstract_noid abstract_decl_array_or_param_seq_opt declarator_end]
+ | [ptr_operator_seq `( sub_abstract_declarator `)
+ abstract_decl_array_or_param_seq_opt declarator_end]
+ | [abstract_noid abstract_decl_array_or_param_seq declarator_end]
+ | [`( sub_abstract_declarator `) abstract_decl_array_or_param_seq_opt declarator_end]
+
+ def sub_abstract_declarator
+ [ptr_operator_seq abstract_noid abstract_decl_array_or_param_seq_opt]
+
+ | [ptr_operator_seq `( sub_abstract_declarator `)
+ abstract_decl_array_or_param_seq_opt]
+
+ | [`( sub_abstract_declarator `) abstract_decl_array_or_param_seq_opt]
+
+ def abstract_noid
+ []
+ {
+ # Make scope for declarator.
+ DD: declarator_data = new declarator_data
+ declaratorData->push_tail( DD )
+ }
+
+ def abstract_decl_array_or_param_seq_opt
+ [abstract_decl_array_or_param_seq_opt abstract_decl_array_or_param]
+ | []
+
+ def abstract_decl_array_or_param_seq
+ [abstract_decl_array_or_param_seq abstract_decl_array_or_param]
+ | [abstract_decl_array_or_param]
+
+ def abstract_decl_array_or_param
+ [`[ constant_expression_opt `]]
+ | [`( parameter_declaration_clause `) cv_qualifier_rep
+ exception_specification_opt]
+
+ def parameter_declaration_clause
+ [pdc_start parameter_declaration_list]
+ | [pdc_start parameter_declaration_list `...]
+ | [pdc_start parameter_declaration_list `, `...]
+ | [pdc_start `...]
+ | [pdc_start]
+
+ def pdc_start
+ []
+ {
+ if !declaratorData->tail->pdcScope {
+ # We are going to need a scope for the declarator.
+ pdcScope: lang_object = createLangObject( 0 '<pdc_scope>' lookupNs->tail->Obj )
+
+ E1: list_lang_object_el = new list_lang_object_el
+ E1->Obj = pdcScope
+ lookupNs->push_tail( E1 )
+
+ E2: list_lang_object_el = new list_lang_object_el
+ E2->Obj = pdcScope
+ declNs->push_tail( E2 )
+
+ declaratorData->tail->pdcScope = pdcScope
+ declaratorData->tail->lookupObj = pdcScope
+ # LOG print( 'opening <pdc_scope>\n' )
+ }
+ }
+
+ def parameter_declaration_list
+ [parameter_declaration_list `, parameter_declaration]
+ | [parameter_declaration]
+
+ def parameter_declaration
+ [declaration_start parameter_declaration_forms declaration_end]
+
+ # Ordering the productions such that decl_specifier_sing is tried first is good
+ # for performance.
+ def parameter_declaration_forms
+ [decl_specifier_mult_seq_opt decl_specifier_sing decl_specifier_mult_seq_opt
+ param_maybe_declarator maybe_parameter_init]
+
+ | [decl_specifier_mult_seq param_maybe_declarator maybe_parameter_init]
+
+ def param_maybe_declarator
+ [abstract_declarator]
+ | [declarator]
+ | []
+
+ def maybe_parameter_init
+ [`= constant_expression]
+ | []
+
+ def ptr_operator
+ [`&]
+ | [root_qual_opt nested_name_specifier_opt `* cv_qualifier_rep]
+
+ def ptr_operator_seq
+ [ptr_operator_seq ptr_operator]
+ | [ptr_operator]
+
+ def ptr_operator_seq_opt
+ [ptr_operator_seq_opt ptr_operator]
+ | []
+
+ #
+ # Functions
+ #
+
+ def function_definition
+ [function_def_declaration ctor_initializer_opt function_body function_def_end]
+
+ def function_def_declaration
+ [declaration_start function_def_declaration_forms declaration_end]
+
+ def function_def_declaration_forms
+ [decl_specifier_mult_seq_opt decl_specifier_sing
+ decl_specifier_mult_seq_opt function_def_declarator]
+ | [decl_specifier_mult_seq function_def_declarator]
+ | [function_def_declarator]
+
+ def function_def_declarator
+ [declarator]
+ {
+ # The lookupObj from the declarator is the deepest lookup object found
+ # while parsing the declarator. Make it visible in the function body.
+ # This could be the args, the qualObj, or the parent to the function.
+ E: list_lang_object_el = new list_lang_object_el
+ E->Obj = r1.lookupObj
+ lookupNs->push_tail( E )
+ }
+
+ def function_def_end
+ []
+ {
+ # Pop the lookup object.
+ lookupNs->pop_tail()
+ }
+
+ def function_body
+ [function_body_begin `{ statement_rep function_body_end `}]
+
+ def function_body_begin
+ []
+ {
+ newFunctionBody: lang_object = createLangObject( 0
+ '<function_body_begin>' lookupNs->tail->Obj )
+
+ E1: list_lang_object_el = new list_lang_object_el
+ E1->Obj = newFunctionBody
+ lookupNs->push_tail( E1 )
+
+ E2: list_lang_object_el = new list_lang_object_el
+ E2->Obj = newFunctionBody
+ declNs->push_tail( E2 )
+
+ IntEl: list_int_el = new list_int_el
+ IntEl->Int = 0
+ templDecl->push_tail( IntEl )
+ # LOG print( 'opening <function_body>\n' )
+ }
+
+ def function_body_end
+ []
+ {
+ # First undoes the function body begin work. Then undoes the setup in
+ # function_def_declarator.
+ declNs->pop_tail()
+ lookupNs->pop_tail()
+ templDecl->pop_tail()
+ # LOG print( 'closing <function_body>\n' )
+ }
+
+
+
+ #
+ # Classs
+ #
+
+ int declaredClassType()
+ {
+ if declarationData->tail->isTemplate {
+ return TemplateClassType
+ } else {
+ return ClassType
+ }
+ }
+
+ def class_specifier
+ [class_head base_clause_opt `{ class_member_rep class_body_end `}]
+ {
+ # FIXME: reparse not implemented yet
+ # FIXME FIXME: reparse is actually implemented now implemented
+ # # Visit class function bodies, but skip nested classes.
+ # for CFB: class_function_body in lhs {
+ # skipping class_specifier
+ #
+ # # Reparse the text of the class function body as a function body
+ # function_body FB = parse function_body[ $CFB ]
+ #
+ # # Replace the class function body with the parsed function body.
+ # CFB = cons class_function_body [FB.tree]
+ # }
+ }
+
+ def class_head
+ [class_key]
+ {
+ nsType: int = declaredClassType()
+
+ # LOG print( 'creating new anonymous class\n' )
+ newClass: lang_object = createLangObject( nsType
+ '<anon_class>' lookupNs->tail->Obj )
+
+ E1: list_lang_object_el = new list_lang_object_el
+ E1->Obj = newClass
+ lookupNs->push_tail( E1 )
+
+ E2: list_lang_object_el = new list_lang_object_el
+ E2->Obj = newClass
+ declNs->push_tail( E2 )
+ }
+
+ | [class_key nested_name_specifier_opt class_head_name]
+ {
+ Id: lookup_id = lookup_id in r3
+ name: str = Id.data
+
+ # Get the ns the class is declared in.
+ parentObj: lang_object = declNs->tail->Obj
+ if Id.qualObj
+ parentObj = Id.qualObj
+
+ # Look for the class in the given scope.
+ declaredClass: lang_object = findClass( parentObj name )
+ if !declaredClass
+ declaredClass = findTemplateClass( parentObj name )
+
+ if !declaredClass {
+ # LOG print( 'creating new class: ' name '\n' )
+
+ # Class does not exist in the parent scope, create it.
+ nsType: int = declaredClassType()
+
+ declaredClass = createLangObject( nsType name lookupNs->tail->Obj )
+
+ # FIXME: handle friends. Make the class visible only if we are NOT
+ # in a friend declaration. The new class object is necessary to
+ # properly process the body of the class.
+ if declarationData->tail->isFriend == 0
+ insertObject( parentObj name declaredClass )
+ }
+
+ # Push the found/new class.
+ E1: list_lang_object_el = new list_lang_object_el
+ E1->Obj = declaredClass
+ lookupNs->push_tail( E1 )
+
+ E2: list_lang_object_el = new list_lang_object_el
+ E2->Obj = declaredClass
+ declNs->push_tail( E2 )
+ }
+
+ | [class_key nested_name_specifier_opt templ_class_id
+ templ_arg_open template_argument_list_opt templ_arg_close]
+ {
+ match r3 [Id: lookup_id]
+ id: str = Id.data
+ classObj: lang_object = Id.obj
+
+ # TODO: Try to find the specializaition in the template class object.
+ # TypeList typeList;
+ # makeTypeList( typeList $6->last );
+
+ declaredClass: lang_object
+ #declaredClass = classObj->findSpecExact( typeList );
+ if !declaredClass {
+ # LOG print( 'making new template specialization\n' )
+ nsType: int = declaredClassType()
+ declaredClass = createLangObject( nsType id lookupNs->tail->Obj )
+ # LOG print( 'declaredClass: ' declaredClass '\n' )
+ declaredClass->specializationOf = classObj
+ # $$->typeListMapEl = classObj->typeListMap.insert( typeList declaredClass );
+ }
+
+ # Push the found/new class.
+ E1: list_lang_object_el = new list_lang_object_el
+ E1->Obj = declaredClass
+ lookupNs->push_tail( E1 )
+
+ E2: list_lang_object_el = new list_lang_object_el
+ E2->Obj = declaredClass
+ declNs->push_tail( E2 )
+ }
+
+ def class_body_end
+ []
+ {
+ # Pop the class ns.
+ lookupNs->pop_tail()
+ declNs->pop_tail()
+
+ # LOG print( 'closing off class\n' )
+ }
+
+ def class_head_name
+ [class_id]
+ | [templ_class_id]
+ | [namespace_id]
+ | [typedef_id]
+ | [enum_id]
+ | [unknown_id]
+ | [identifier]
+ | [template_id]
+
+ def class_key
+ [`class]
+ | [`struct]
+ | [`union]
+
+ def class_member_rep
+ [class_member_rep class_member]
+ | []
+
+ def class_member
+ [member_declaration]
+ | [access_specifier `:]
+
+ def member_declaration
+ [declaration_start member_declaration_forms declaration_end `;]
+ | [class_function_definition]
+ | [using_declaration]
+ | [template_declaration]
+
+ def class_function_definition
+ [function_def_declaration ctor_initializer_opt class_function_body function_def_end]
+
+ lex
+ token cfb_open /'{'/
+ token cfb_close /'}'/
+ token cfb_string /
+ "'" ( [^'\\\n] | '\\' any )* "'" |
+ '"' ( [^"\\\n] | '\\' any )* '"'/
+ token cfb_comment /
+ ( '/*' (any | '\n')* :>> '*/' ) |
+ ( '//' any* :> '\n' )/
+ token cfb_data /[^{}'"/]+ | '/'/
+ end
+
+ def cfb_item
+ [cfb_data]
+ | [cfb_string]
+ | [cfb_comment]
+ | [cfb_open cfb_item* cfb_close]
+
+ def cfb_conts
+ [cfb_item* cfb_close]
+
+
+
+ def class_function_body
+ # ['{' cfb_conts]
+ #| [function_body]
+ [function_body]
+
+ # Get better performance if the form with decl_specifier_sing comes first.
+ def member_declaration_forms
+ [decl_specifier_mult_seq_opt decl_specifier_sing
+ decl_specifier_mult_seq_opt member_declarator_list_opt]
+ | [decl_specifier_mult_seq_opt member_declarator_list_opt]
+
+ def member_declarator_list_opt
+ [member_declarator_list]
+ | []
+
+ def member_declarator_list
+ [member_declarator_list `, member_declarator]
+ | [member_declarator]
+
+ def member_declarator
+ [declarator]
+ | [declarator `= constant_expression]
+ | [declarator `: constant_expression]
+ | [`: constant_expression]
+
+ def access_specifier
+ [`private]
+ | [`protected]
+ | [`public]
+
+ def access_specifier_opt
+ [access_specifier]
+ | []
+
+ def using_declaration
+ [`using id_expression `;]
+ {
+ obj: lang_object = r2.lookupId.obj
+ if obj
+ insertObject( declNs->tail->Obj obj->name obj )
+ }
+
+ | [`using type_id `;]
+ {
+ obj: lang_object = r2.lookupId.obj
+ if obj
+ insertObject( declNs->tail->Obj obj->name obj )
+ }
+
+ def using_directive
+ [`using `namespace root_qual_opt nested_name_specifier_opt
+ namespace_id `;]
+ {
+ # This uses a simple, incomplete guard against cycles in the graph of
+ # using namespaces. A more sophisticated and complete guard would look
+ # for longer cycles as well. Note that even gcc 3.3.5 does not bother.
+ match r5 [Id: lookup_id]
+ usingObject: lang_object = Id.obj
+ inObject: lang_object = declNs->tail->Obj
+ if usingObject != inObject {
+ E: list_lang_object_el = new list_lang_object_el
+ E->Obj = usingObject
+ inObject->inherited->push_tail( E )
+ }
+ }
+
+
+ #
+ # Derived classes
+ #
+
+ def base_clause_opt
+ [base_clause]
+ | []
+
+ def base_clause
+ [`: base_specifier_list]
+
+ def base_specifier_list
+ [base_specifier_list `, base_specifier]
+ | [base_specifier]
+
+ int addBaseSpecifier( inObject: lang_object inheritedObject: lang_object )
+ {
+ # Resolve typedefs.
+ if inheritedObject->typeId == TypedefType
+ inheritedObject = inheritedObject->typedefOf
+
+ E: list_lang_object_el = new list_lang_object_el
+ E->Obj = inheritedObject
+ inObject->inherited->push_tail( E )
+ }
+
+ def base_specifier
+ [root_qual_opt nested_name_specifier_opt type_name]
+ {
+ addBaseSpecifier( declNs->tail->Obj r3.lookupId.obj )
+ }
+
+ | [`virtual access_specifier_opt root_qual_opt nested_name_specifier_opt type_name]
+ {
+ addBaseSpecifier( declNs->tail->Obj r5.lookupId.obj )
+ }
+
+ | [access_specifier virtual_opt root_qual_opt nested_name_specifier_opt type_name]
+ {
+ addBaseSpecifier( declNs->tail->Obj r5.lookupId.obj )
+ }
+
+ def virtual_opt
+ [`virtual]
+ | []
+
+ #
+ # Special member functions
+ #
+
+ def conversion_function_id
+ [`operator conversion_type_id]
+
+ def conversion_type_id
+ [necs_type_specifier_seq ptr_operator_seq_opt]
+
+ def ctor_initializer_opt
+ [ctor_initializer]
+ | []
+
+ def ctor_initializer
+ [`: mem_initializer_list]
+
+ def mem_initializer_list
+ [mem_initializer_list `, mem_initializer]
+ | [mem_initializer]
+
+ def mem_initializer
+ [mem_initializer_id `( expression_opt `)]
+
+ def mem_initializer_id
+ [root_qual_opt nested_name_specifier_opt unknown_id]
+ | [root_qual_opt nested_name_specifier_opt identifier]
+ | [root_qual_opt nested_name_specifier_opt type_name]
+ | [root_qual_opt nested_name_specifier_opt template_name]
+
+
+ #
+ # Overloading
+ #
+ def operator_function_id
+ [`operator operator]
+
+ def operator
+ [`+] | [`-] | [`*] | [`/] | [`=] | [`<] | [`>] | [`&] | [`|] |
+ [`^] | [`%] | [`~] | [`!] | [`( `)] | [`[ `]] | [`new] |
+ [`delete] | [`->] | [`++] | [`--] | [`*=] | [`/=] | [`%=] |
+ [`+=] | [`-=] | [`>>=] | [`<<=] | [`&=] | [`^=] | [`|=] | [`==] |
+ [`!=] | [`&&] | [`||] | [lt_eq] | [gt_eq] | [shift_left] | [shift_right]
+
+ def lt_eq
+ [`< `=]
+ # try {
+ # if ( $2->leader != 0 ) {
+ # #ifdef LOG_REDUCE
+ # cerr << "rejecting less-than equals-to" << endl;
+ # #endif
+ # reject();
+ # }
+ # };
+
+ def gt_eq
+ [`> `=]
+ # try {
+ # if ( $2->leader != 0 ) {
+ # #ifdef LOG_REDUCE
+ # cerr << "rejecting greater-than equals-to" << endl;
+ # #endif
+ # reject();
+ # }
+ # };
+
+ def shift_left
+ [`< `<]
+ # try {
+ # if ( $2->leader != 0 ) {
+ # #ifdef LOG_REDUCE
+ # cerr << "rejecting shift left" << endl;
+ # #endif
+ # reject();
+ # }
+ # };
+
+ def shift_right
+ [`> `>]
+ # try {
+ # if ( $2->leader != 0 ) {
+ # #ifdef LOG_REDUCE
+ # cerr << "rejecting shift right" << endl;
+ # #endif
+ # reject();
+ # }
+ # };
+
+ #
+ # Templates
+ #
+
+ def template_declaration
+ [template_declaration_params declaration]
+ {
+ templDecl->pop_tail()
+ templateParamNs->pop_tail()
+ }
+
+ def template_declaration_params
+ [`template `< tpl_start template_parameter_list `>]
+ {
+ IntEl: list_int_el = new list_int_el
+ IntEl->Int = 1
+ templDecl->push_tail( IntEl )
+ }
+
+ | [`export `template `< tpl_start template_parameter_list `>]
+ {
+ IntEl: list_int_el = new list_int_el
+ IntEl->Int = 1
+ templDecl->push_tail( IntEl )
+ }
+
+ def tpl_start
+ []
+ {
+ # Create a new scope for the template parameters.
+ newTemplateParamScope: lang_object =
+ createLangObject( 0 '<tpl_start>' lookupNs->tail->Obj )
+
+ E: list_lang_object_el = new list_lang_object_el
+ E->Obj = newTemplateParamScope
+ templateParamNs->push_tail( E )
+ }
+
+ def template_parameter_list
+ [template_parameter_list `, template_parameter]
+ | [template_parameter]
+
+ def template_parameter
+ [type_parameter]
+ | [template_parameter_declaration]
+
+ def template_parameter_declaration
+ [declaration_start template_parameter_declaration_forms declaration_end]
+
+ def template_parameter_declaration_forms
+ [decl_specifier_mult_seq param_maybe_declarator maybe_parameter_init]
+
+ | [temp_param_decl_specifier_sing decl_specifier_mult_seq_opt
+ param_maybe_declarator maybe_parameter_init]
+
+ | [decl_specifier_mult_seq temp_param_decl_specifier_sing
+ decl_specifier_mult_seq_opt param_maybe_declarator maybe_parameter_init]
+
+ def temp_param_decl_specifier_sing
+ [temp_param_type_specifier_sing]
+
+ # Template parameters cannot support elaborated type specifer or class specifier.
+ def temp_param_type_specifier_sing
+ [templ_simple_type_specifier]
+ | [enum_specifier]
+
+ def templ_simple_type_specifier
+ [simple_type_specifier_name]
+ | [simple_type_specifier_kw_seq]
+
+ def type_parameter
+ [`class type_param_id type_param_init_opt]
+ {
+ Id: lookup_id = lookup_id in r2
+ if Id {
+ # The lookup ns should be a template param scope.
+ newClass: lang_object =
+ createLangObject( ClassType Id.data lookupNs->tail->Obj )
+ insertObject( templateParamNs->tail->Obj Id.data newClass )
+ }
+ }
+
+ | [`typename type_param_id type_param_init_opt]
+ {
+ Id: lookup_id = lookup_id in r2
+ if Id {
+ # The lookup ns should be a template param scope.
+ newClass: lang_object =
+ createLangObject( ClassType Id.data lookupNs->tail->Obj )
+ insertObject( templateParamNs->tail->Obj Id.data newClass )
+ }
+ }
+
+ | [`template `< tpl_start template_parameter_list `>
+ `class type_param_id templ_type_param_init_opt]
+ {
+ Id: lookup_id = lookup_id in r7
+ if Id {
+ newClass: lang_object =
+ createLangObject( TemplateClassType Id.data lookupNs->tail->Obj )
+ insertObject( templateParamNs->tail->Obj Id.data newClass )
+ }
+ }
+
+ def templ_type_param_init_opt
+ [`= id_expression]
+ | []
+
+ def type_param_init_opt
+ [`= type_id]
+ | []
+
+ def type_param_id
+ [namespace_id]
+ | [typedef_id]
+ | [enum_id]
+ | [class_id]
+ | [templ_class_id]
+ | [identifier]
+ | [template_id]
+ | [unknown_id]
+ | []
+
+ def template_argument_list_opt
+ [template_argument_list]
+ | []
+
+ def template_argument_list
+ [template_argument_list `, template_argument]
+ | [template_argument]
+
+ def template_argument
+ [type_id]
+ | [assignment_expression]
+
+ def explicit_instantiation
+ [`template declaration]
+ | [declaration_start decl_specifier_mult_seq `template declaration declaration_end]
+
+ def explicit_specialization
+ [`template `< `> declaration]
+
+ ## Not sure what this one is about?
+ #explicit_specialization:
+ # declaration_start decl_specifier_mult_seq KW_Template '<' '>'
+ # declaration declaration_end;
+
+
+ #
+ # Original namespace definition
+ #
+
+ def original_namespace_definition
+ [orig_namespace_def_name `{ declaration* namespace_end `}]
+
+ def orig_namespace_def_name [`namespace unknown_id]
+ {
+ match r2 [Id: lookup_id]
+ nspace: lang_object = createLangObject(
+ NamespaceType Id.data lookupNs->tail->Obj )
+
+ # Insert the new object into the dictionary of the parent.
+ insertObject( curNamespace->tail->Obj Id.data nspace )
+
+ # Push the namespace
+ E1: list_lang_object_el = new list_lang_object_el
+ E1->Obj = nspace
+ curNamespace->push_tail( E1 )
+
+ E2: list_lang_object_el = new list_lang_object_el
+ E2->Obj = nspace
+ declNs->push_tail( E2 )
+
+ E3: list_lang_object_el = new list_lang_object_el
+ E3->Obj = nspace
+ lookupNs->push_tail( E3 )
+
+ # LOG print( 'created original namespace: ' Id.data '\n' )
+ }
+
+ def namespace_end []
+ {
+ # Pop the namespace.
+ curNamespace->pop_tail()
+ declNs->pop_tail()
+ lookupNs->pop_tail()
+
+ # LOG print( 'closed namespace\n' )
+ }
+
+ #
+ # Extension namespace definition
+ #
+
+ def extension_namespace_definition
+ [ext_namespace_def_name `{ declaration* namespace_end `}]
+
+ def ext_namespace_def_name [`namespace namespace_id]
+ {
+ match r2 [Id: lookup_id]
+ nspace: lang_object = Id.obj
+
+ # Push the namespace
+ E1: list_lang_object_el = new list_lang_object_el
+ E1->Obj = nspace
+ curNamespace->push_tail( E1 )
+
+ E2: list_lang_object_el = new list_lang_object_el
+ E2->Obj = nspace
+ declNs->push_tail( E2 )
+
+ E3: list_lang_object_el = new list_lang_object_el
+ E3->Obj = nspace
+ lookupNs->push_tail( E3 )
+
+ # LOG print( 'found extended namespace: ' Id.data '\n' )
+ }
+
+ #
+ # Unnamed namespace definition
+ #
+ def unnamed_namespace_definition
+ [unnamed_namespace_def_name `{ declaration* namespace_end `}]
+
+ def unnamed_namespace_def_name [`namespace]
+ {
+ nspace: lang_object = createLangObject(
+ NamespaceType '<unnamed_namespace>'
+ lookupNs->tail->Obj )
+
+ # Push the namespace
+ E1: list_lang_object_el = new list_lang_object_el
+ E1->Obj = nspace
+ curNamespace->push_tail( E1 )
+
+ E2: list_lang_object_el = new list_lang_object_el
+ E2->Obj = nspace
+ declNs->push_tail( E2 )
+
+ E3: list_lang_object_el = new list_lang_object_el
+ E3->Obj = nspace
+ lookupNs->push_tail( E3 )
+
+ # LOG print( 'parsed unnamed namespace\n' )
+ }
+
+ #
+ # linkage_specification
+ #
+ def linkage_specification
+ [`extern TK_DoubleLit `{ declaration* `}]
+ | [`extern TK_DoubleLit declaration]
+
+ #
+ # Exception Handling.
+ #
+
+ def try_block
+ [`try compound_statement handler_seq]
+
+ def handler_seq
+ [handler_seq handler]
+ | [handler]
+
+ def handler
+ [`catch `( exception_declaration `) compound_statement]
+
+ def exception_declaration
+ [type_specifier_seq declarator]
+ | [type_specifier_seq abstract_declarator]
+ | [type_specifier_seq]
+ | [`...]
+
+ def throw_expression
+ [`throw assignment_expression]
+ | [`throw]
+
+ def exception_specification_opt
+ [exception_specification]
+ | []
+
+ def exception_specification
+ [`throw `( type_id_list_opt `)]
+
+ def type_id_list_opt
+ [type_id_list]
+ | []
+
+ def type_id_list
+ [type_id_list `, type_id]
+ | [type_id]
+
+ def start
+ [declaration*]
+
+ #
+ # Grammar done.
+ #
+
+ int printObject( indent: str obj: lang_object )
+ {
+ print( indent obj->name )
+
+ if obj->objectMap->length > 0
+ print( ' {\n' )
+
+ ChildNames: map_list_lang_object = obj->objectMap
+ MapEl: map_list_lang_object_el = ChildNames->head
+ while ( MapEl ) {
+ El: list_lang_object_el = MapEl->List->head
+ while ( El ) {
+ printObject( indent + ' ' El->Obj )
+ El = El->next
+ }
+ MapEl = MapEl->next
+ }
+
+ if obj->objectMap->length > 0
+ print( indent '}' )
+
+ print( '\n' )
+ }
+
+end # lookup
+
+#
+# Global data declarations
+#
+
+Lookup: lookup = new lookup
+
+# Constants for language object types.
+Lookup->NamespaceType = typeid<lookup::namespace_id>
+Lookup->ClassType = typeid<lookup::class_id>
+Lookup->TemplateClassType = typeid<lookup::templ_class_id>
+Lookup->EnumType = typeid<lookup::enum_id>
+Lookup->IdType = typeid<lookup::identifier>
+Lookup->TypedefType = typeid<lookup::typedef_id>
+Lookup->TemplateIdType = typeid<lookup::template_id>
+
+
+# Object stacks.
+Lookup->curNamespace = new lookup::list_lang_object
+Lookup->declNs = new lookup::list_lang_object
+Lookup->lookupNs = new lookup::list_lang_object
+Lookup->qualNs = new lookup::list_lang_object
+Lookup->templateParamNs = new lookup::list_lang_object
+
+# Declaration, declarator data.
+Lookup->declarationData = new lookup::list_declaration_data
+Lookup->declaratorData = new lookup::list_declarator_data
+
+# Template declarations
+Lookup->templDecl = new lookup::list_int
+
+# Root namespace object
+Lookup->rootNamespace = createLangObject( Lookup->NamespaceType '<root_namespace>' nil )
+
+# Initialize the namespace and declaration stacks with the root namespace
+E1: lookup::list_lang_object_el = new lookup::list_lang_object_el
+E1->Obj = Lookup->rootNamespace
+Lookup->curNamespace->push_tail( E1 )
+
+E2: lookup::list_lang_object_el = new lookup::list_lang_object_el
+E2->Obj = Lookup->rootNamespace
+Lookup->declNs->push_tail( E2 )
+
+E3: lookup::list_lang_object_el = new lookup::list_lang_object_el
+E3->Obj = Lookup->rootNamespace
+Lookup->lookupNs->push_tail( E3 )
+
+# Start with no qualification (note variables are initialized to zero)
+E4: lookup::list_lang_object_el = new lookup::list_lang_object_el
+E4->Obj = nil
+Lookup->qualNs->push_tail( E4 )
+
+IntEl: lookup::list_int_el = new lookup::list_int_el
+IntEl->Int = 0
+Lookup->templDecl->push_tail( IntEl )
+
+DD: lookup::declaration_data = new lookup::declaration_data
+DD->isTypedef = 0
+DD->isFriend = 0
+DD->isTemplate = 0
+Lookup->declarationData->push_tail( DD )
+
+parse S: lookup::start( Lookup )[ stdin ]
+if ! S {
+ print( error )
+ exit( 1 )
+}
+
+print( '***** NAMSPACES *****\n' )
+printObject( '' Lookup->rootNamespace )
+print( '***** UNKNOWN DECLARATORS *****\n' )
+for DI: lookup::declarator_id in S {
+ if match DI
+ [lookup::root_qual_opt lookup::nested_name_specifier_opt lookup::`~ UID: lookup::unknown_id]
+ {
+ print( UID '\n' )
+ }
+}
+##### IN #####
+namespace ns1
+{
+ namespace sub1 { class A {}; }
+ namespace sub2 { class B {}; }
+}
+
+namespace ns2
+{
+ int i = b;
+ class C
+ {
+ };
+
+ using namespace ns1;
+}
+
+ns2::sub1::A a;
+
+struct A
+{
+ struct B {};
+};
+
+struct C
+{
+ struct D : virtual public A {};
+};
+
+C::D::A d;
+
+C c;
+
+struct C
+{
+
+};
+
+enum E
+{
+ C,
+ b
+};
+
+E e;
+
+enum E
+{
+ C,
+ b
+};
+
+
+int i;
+class C
+{
+ int j;
+};
+
+class D
+{
+ int ~D();
+};
+
+int C::k;
+int C::~C;
+
+typedef int Int;
+
+class C {};
+void ~C( );
+void C::operator +( int i );
+
+int i;
+
+//void operator C( void k );
+
+class C
+{
+
+};
+
+int C::f( int i, int j( void v ) );
+class C
+{
+ class D {};
+
+ typedef C I;
+
+ I::D i;
+};
+
+C c;
+
+void function( int i, int j )
+{
+ function();
+}
+
+
+
+class B { class Find {}; };
+
+typedef B T;
+
+class C : public T
+{
+ Find find;
+};
+
+
+template <class X> struct Y
+{
+ X t;
+ void f();
+};
+
+template <class X> void Y<X>::f();
+template <class X> struct Y
+{
+ class Z {};
+};
+
+class Y<int>
+{
+ int i;
+};
+
+//void f( class C<int> i, int j );
+
+int f( int (*) [](), void );
+void f();
+class C
+{
+ class D {};
+ void g();
+};
+
+//typename C c;
+
+class C
+{
+ class D {};
+ int f();
+};
+
+int f()
+{
+}
+
+int C::f()
+{
+ D d;
+}
+##### EXP #####
+***** NAMSPACES *****
+<root_namespace> {
+ A {
+ B
+ }
+ B {
+ Find
+ }
+ C {
+ D
+ }
+ C
+ C
+ C
+ C {
+ j
+ }
+ C
+ C
+ C
+ C {
+ D
+ I
+ i
+ }
+ C {
+ find
+ }
+ C {
+ D
+ g
+ }
+ C {
+ D
+ f
+ }
+ D
+ E
+ E
+ T
+ Y {
+ Z
+ f
+ t
+ }
+ a
+ b
+ b
+ c
+ c
+ d
+ e
+ f
+ f
+ f
+ i
+ i
+ Int
+ ns1 {
+ sub1 {
+ A
+ }
+ sub2 {
+ B
+ }
+ }
+ ns2 {
+ C
+ i
+ }
+ function
+}
+***** UNKNOWN DECLARATORS *****
+C