Skip to content

Commit 24aca54

Browse files
committed
Add: Identifier concatenation with '##'
1 parent eba7065 commit 24aca54

3 files changed

Lines changed: 48 additions & 38 deletions

File tree

nml/parser.py

Lines changed: 44 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ def p_include_define_list(self, t):
149149
t[0] = t[1] | t[3]
150150

151151
def p_include_define(self, t):
152-
"include_define : ID EQ expression"
152+
"include_define : identifier EQ expression"
153153
t[0] = {t[1].value: t[3]}
154154

155155
def p_main_block(self, t):
@@ -190,6 +190,14 @@ def p_main_block(self, t):
190190
| constant"""
191191
t[0] = t[1]
192192

193+
def p_identifier(self, t):
194+
"""identifier : ID
195+
| identifier CONCAT identifier"""
196+
if len(t) == 4:
197+
t[0] = expression.Identifier(t[1].value + t[3].value)
198+
else:
199+
t[0] = t[1]
200+
193201
#
194202
# Expressions
195203
#
@@ -198,7 +206,7 @@ def p_expression(self, t):
198206
| FLOAT
199207
| param
200208
| variable
201-
| ID
209+
| identifier
202210
| STRING_LITERAL
203211
| string"""
204212
t[0] = t[1]
@@ -284,7 +292,7 @@ def p_variable(self, t):
284292
t[0].pos = t.lineno(1)
285293

286294
def p_function(self, t):
287-
"expression : ID LPAREN expression_list RPAREN"
295+
"expression : identifier LPAREN expression_list RPAREN"
288296
t[0] = expression.FunctionCall(t[1], t[3], t[1].pos)
289297

290298
def p_array(self, t):
@@ -305,7 +313,7 @@ def p_assignment_list(self, t):
305313
t[0] = t[1] + [t[2]]
306314

307315
def p_assignment(self, t):
308-
"assignment : ID COLON expression SEMICOLON"
316+
"assignment : identifier COLON expression SEMICOLON"
309317
t[0] = assignment.Assignment(t[1], t[3], t[1].pos)
310318

311319
def p_param_desc(self, t):
@@ -325,7 +333,7 @@ def p_setting_list(self, t):
325333
t[0] = t[1] + [t[2]]
326334

327335
def p_setting(self, t):
328-
"setting : ID LBRACE setting_value_list RBRACE"
336+
"setting : identifier LBRACE setting_value_list RBRACE"
329337
t[0] = grf.ParameterSetting(t[1], t[3])
330338

331339
def p_setting_value_list(self, t):
@@ -341,7 +349,7 @@ def p_setting_value(self, t):
341349
t[0] = t[1]
342350

343351
def p_names_setting_value(self, t):
344-
"setting_value : ID COLON LBRACE name_string_list RBRACE SEMICOLON"
352+
"setting_value : identifier COLON LBRACE name_string_list RBRACE SEMICOLON"
345353
t[0] = assignment.Assignment(t[1], t[4], t[1].pos)
346354

347355
def p_name_string_list(self, t):
@@ -375,8 +383,8 @@ def p_expression_list(self, t):
375383
t[0] = [] if len(t) == 1 else t[1]
376384

377385
def p_non_empty_id_list(self, t):
378-
"""non_empty_id_list : ID
379-
| non_empty_id_list COMMA ID"""
386+
"""non_empty_id_list : identifier
387+
| non_empty_id_list COMMA identifier"""
380388
if len(t) == 2:
381389
t[0] = [t[1]]
382390
else:
@@ -428,8 +436,8 @@ def p_property_list(self, t):
428436
t[0] = t[1] + [t[2]]
429437

430438
def p_property_assignment(self, t):
431-
"""property_assignment : ID COLON expression SEMICOLON
432-
| ID COLON expression UNIT SEMICOLON
439+
"""property_assignment : identifier COLON expression SEMICOLON
440+
| identifier COLON expression UNIT SEMICOLON
433441
| NUMBER COLON expression SEMICOLON
434442
| NUMBER COLON expression UNIT SEMICOLON"""
435443
name = t[1]
@@ -557,9 +565,9 @@ def p_produce_cargo_list(self, t):
557565
t[0] = t[2]
558566

559567
def p_produce(self, t):
560-
"""produce : PRODUCE LPAREN ID COMMA expression_list RPAREN SEMICOLON
561-
| PRODUCE LPAREN ID COMMA produce_cargo_list COMMA produce_cargo_list COMMA expression RPAREN
562-
| PRODUCE LPAREN ID COMMA produce_cargo_list COMMA produce_cargo_list RPAREN"""
568+
"""produce : PRODUCE LPAREN identifier COMMA expression_list RPAREN SEMICOLON
569+
| PRODUCE LPAREN identifier COMMA produce_cargo_list COMMA produce_cargo_list COMMA expression RPAREN
570+
| PRODUCE LPAREN identifier COMMA produce_cargo_list COMMA produce_cargo_list RPAREN"""
563571
if len(t) == 8:
564572
t[0] = produce.ProduceOld([t[3]] + t[5], t.lineno(1))
565573
elif len(t) == 11:
@@ -572,7 +580,7 @@ def p_produce(self, t):
572580
#
573581
def p_real_sprite(self, t):
574582
"""real_sprite : LBRACKET expression_list RBRACKET
575-
| ID COLON LBRACKET expression_list RBRACKET"""
583+
| identifier COLON LBRACKET expression_list RBRACKET"""
576584
if len(t) == 4:
577585
t[0] = real_sprite.RealSprite(param_list=t[2], poslist=[t.lineno(1)])
578586
else:
@@ -597,19 +605,19 @@ def p_recolour_assignment_3(self, t):
597605

598606
def p_recolour_sprite(self, t):
599607
"""real_sprite : RECOLOUR_SPRITE LBRACE recolour_assignment_list RBRACE
600-
| ID COLON RECOLOUR_SPRITE LBRACE recolour_assignment_list RBRACE"""
608+
| identifier COLON RECOLOUR_SPRITE LBRACE recolour_assignment_list RBRACE"""
601609
if len(t) == 5:
602610
t[0] = real_sprite.RecolourSprite(mapping=t[3], poslist=[t.lineno(1)])
603611
else:
604612
t[0] = real_sprite.RecolourSprite(mapping=t[5], label=t[1], poslist=[t.lineno(1)])
605613

606614
def p_template_declaration(self, t):
607-
"template_declaration : TEMPLATE ID LPAREN id_list RPAREN LBRACE spriteset_contents RBRACE"
615+
"template_declaration : TEMPLATE identifier LPAREN id_list RPAREN LBRACE spriteset_contents RBRACE"
608616
t[0] = spriteblock.TemplateDeclaration(t[2], t[4], t[7], t.lineno(1))
609617

610618
def p_template_usage(self, t):
611-
"""template_usage : ID LPAREN expression_list RPAREN
612-
| ID COLON ID LPAREN expression_list RPAREN"""
619+
"""template_usage : identifier LPAREN expression_list RPAREN
620+
| identifier COLON identifier LPAREN expression_list RPAREN"""
613621
if len(t) == 5:
614622
t[0] = real_sprite.TemplateUsage(t[1], t[3], None, t.lineno(1))
615623
else:
@@ -627,31 +635,31 @@ def p_spriteset_contents(self, t):
627635

628636
def p_replace(self, t):
629637
"""replace : REPLACESPRITE LPAREN expression_list RPAREN LBRACE spriteset_contents RBRACE
630-
| REPLACESPRITE ID LPAREN expression_list RPAREN LBRACE spriteset_contents RBRACE"""
638+
| REPLACESPRITE identifier LPAREN expression_list RPAREN LBRACE spriteset_contents RBRACE"""
631639
if len(t) == 9:
632640
t[0] = replace.ReplaceSprite(t[4], t[7], t[2], t.lineno(1))
633641
else:
634642
t[0] = replace.ReplaceSprite(t[3], t[6], None, t.lineno(1))
635643

636644
def p_replace_new(self, t):
637645
"""replace_new : REPLACENEWSPRITE LPAREN expression_list RPAREN LBRACE spriteset_contents RBRACE
638-
| REPLACENEWSPRITE ID LPAREN expression_list RPAREN LBRACE spriteset_contents RBRACE"""
646+
| REPLACENEWSPRITE identifier LPAREN expression_list RPAREN LBRACE spriteset_contents RBRACE"""
639647
if len(t) == 9:
640648
t[0] = replace.ReplaceNewSprite(t[4], t[7], t[2], t.lineno(1))
641649
else:
642650
t[0] = replace.ReplaceNewSprite(t[3], t[6], None, t.lineno(1))
643651

644652
def p_base_graphics(self, t):
645653
"""base_graphics : BASE_GRAPHICS LPAREN expression_list RPAREN LBRACE spriteset_contents RBRACE
646-
| BASE_GRAPHICS ID LPAREN expression_list RPAREN LBRACE spriteset_contents RBRACE"""
654+
| BASE_GRAPHICS identifier LPAREN expression_list RPAREN LBRACE spriteset_contents RBRACE"""
647655
if len(t) == 9:
648656
t[0] = base_graphics.BaseGraphics(t[4], t[7], t[2], t.lineno(1))
649657
else:
650658
t[0] = base_graphics.BaseGraphics(t[3], t[6], None, t.lineno(1))
651659

652660
def p_font_glyph(self, t):
653661
"""font_glyph : FONTGLYPH LPAREN expression_list RPAREN LBRACE spriteset_contents RBRACE
654-
| FONTGLYPH ID LPAREN expression_list RPAREN LBRACE spriteset_contents RBRACE"""
662+
| FONTGLYPH identifier LPAREN expression_list RPAREN LBRACE spriteset_contents RBRACE"""
655663
if len(t) == 9:
656664
t[0] = font.FontGlyphBlock(t[4], t[7], t[2], t.lineno(1))
657665
else:
@@ -670,12 +678,12 @@ def p_spriteset(self, t):
670678
t[0] = spriteblock.SpriteSet(t[3], t[6], t.lineno(1))
671679

672680
def p_spritegroup_normal(self, t):
673-
"spritegroup : SPRITEGROUP ID LBRACE spriteview_list RBRACE"
681+
"spritegroup : SPRITEGROUP identifier LBRACE spriteview_list RBRACE"
674682
t[0] = spriteblock.SpriteGroup(t[2], t[4], t.lineno(1))
675683

676684
def p_spritelayout(self, t):
677-
"""spritelayout : SPRITELAYOUT ID LBRACE layout_sprite_list RBRACE
678-
| SPRITELAYOUT ID LPAREN id_list RPAREN LBRACE layout_sprite_list RBRACE"""
685+
"""spritelayout : SPRITELAYOUT identifier LBRACE layout_sprite_list RBRACE
686+
| SPRITELAYOUT identifier LPAREN id_list RPAREN LBRACE layout_sprite_list RBRACE"""
679687
if len(t) == 6:
680688
t[0] = spriteblock.SpriteLayout(t[2], [], t[4], t.lineno(1))
681689
else:
@@ -690,8 +698,8 @@ def p_spriteview_list(self, t):
690698
t[0] = t[1] + [t[2]]
691699

692700
def p_spriteview(self, t):
693-
"""spriteview : ID COLON LBRACKET expression_list RBRACKET SEMICOLON
694-
| ID COLON expression SEMICOLON"""
701+
"""spriteview : identifier COLON LBRACKET expression_list RBRACKET SEMICOLON
702+
| identifier COLON expression SEMICOLON"""
695703
if len(t) == 7:
696704
t[0] = spriteblock.SpriteView(t[1], t[4], t.lineno(1))
697705
else:
@@ -706,7 +714,7 @@ def p_layout_sprite_list(self, t):
706714
t[0] = t[1] + [t[2]]
707715

708716
def p_layout_sprite(self, t):
709-
"layout_sprite : ID LBRACE layout_param_list RBRACE"
717+
"layout_sprite : identifier LBRACE layout_param_list RBRACE"
710718
t[0] = spriteblock.LayoutSprite(t[1], t[3], t.lineno(1))
711719

712720
def p_layout_param_list(self, t):
@@ -737,7 +745,7 @@ def p_town_names_param_list(self, t):
737745
t[0] = t[1] + [t[2]]
738746

739747
def p_town_names_param(self, t):
740-
"""town_names_param : ID COLON string SEMICOLON
748+
"""town_names_param : identifier COLON string SEMICOLON
741749
| LBRACE town_names_part_list RBRACE
742750
| LBRACE town_names_part_list COMMA RBRACE"""
743751
if t[1] != "{":
@@ -755,7 +763,7 @@ def p_town_names_part_list(self, t):
755763

756764
def p_town_names_part(self, t):
757765
"""town_names_part : TOWN_NAMES LPAREN expression COMMA expression RPAREN
758-
| ID LPAREN STRING_LITERAL COMMA expression RPAREN"""
766+
| identifier LPAREN STRING_LITERAL COMMA expression RPAREN"""
759767
if t[1] == "town_names":
760768
t[0] = townnames.TownNamesEntryDefinition(t[3], t[5], t.lineno(1))
761769
else:
@@ -765,7 +773,7 @@ def p_town_names_part(self, t):
765773
# Snow line
766774
#
767775
def p_snowline(self, t):
768-
"snowline : SNOWLINE LPAREN ID RPAREN LBRACE snowline_assignment_list RBRACE"
776+
"snowline : SNOWLINE LPAREN identifier RPAREN LBRACE snowline_assignment_list RBRACE"
769777
t[0] = snowline.Snowline(t[3], t[6], t.lineno(1))
770778

771779
#
@@ -789,9 +797,9 @@ def p_cargotable(self, t):
789797
t[0] = cargotable.CargoTable(t[3], t.lineno(1))
790798

791799
def p_cargotable_list(self, t):
792-
"""cargotable_list : ID
800+
"""cargotable_list : identifier
793801
| STRING_LITERAL
794-
| cargotable_list COMMA ID
802+
| cargotable_list COMMA identifier
795803
| cargotable_list COMMA STRING_LITERAL"""
796804
if len(t) == 2:
797805
t[0] = [t[1]]
@@ -822,9 +830,9 @@ def p_tracktypetable_list(self, t):
822830
t[0] = t[1] + [t[3]]
823831

824832
def p_tracktypetable_item(self, t):
825-
"""tracktypetable_item : ID
833+
"""tracktypetable_item : identifier
826834
| STRING_LITERAL
827-
| ID COLON LBRACKET expression_list RBRACKET"""
835+
| identifier COLON LBRACKET expression_list RBRACKET"""
828836
if len(t) == 2:
829837
t[0] = t[1]
830838
else:
@@ -855,7 +863,7 @@ def p_sort_vehicles(self, t):
855863
t[0] = sort_vehicles.SortVehicles(t[3], t.lineno(1))
856864

857865
def p_tilelayout(self, t):
858-
"tilelayout : TILELAYOUT ID LBRACE tilelayout_list RBRACE"
866+
"tilelayout : TILELAYOUT identifier LBRACE tilelayout_list RBRACE"
859867
t[0] = tilelayout.TileLayout(t[2], t[4], t.lineno(1))
860868

861869
def p_tilelayout_list(self, t):

nml/tokens.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ class NMLLexer:
122122
"NUMBER",
123123
"FLOAT",
124124
"UNIT",
125+
"CONCAT",
125126
]
126127

127128
t_PLUS = r"\+"
@@ -157,6 +158,7 @@ class NMLLexer:
157158
t_TERNARY_OPEN = r"\?"
158159
t_COLON = r":"
159160
t_SEMICOLON = r";"
161+
t_CONCAT = r"\#\#"
160162

161163
def t_FLOAT(self, t):
162164
r"\d+\.\d+"

regression/042_include.inc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
param[0] = param[0] + VALUE;
2-
const NAME = VALUE;
3-
param[0] = param[0] + NAME;
2+
const _ ## NAME ## x ## y = VALUE;
3+
param[0] = param[0] + _ ## NAME ## x ## y;

0 commit comments

Comments
 (0)