diff --git a/lib/lrama/lexer.rb b/lib/lrama/lexer.rb index d047994a..72ce9019 100644 --- a/lib/lrama/lexer.rb +++ b/lib/lrama/lexer.rb @@ -213,21 +213,33 @@ def lex_user_code(ss, line, column, lines) string, line = lex_string(ss, "'", line, lines) str << string next + + # $ references + # It need to wrap an identifier with brackets to use ".-" for identifiers when ss.scan(/\$(<[a-zA-Z0-9_]+>)?\$/) # $$, $$ tag = ss[1] ? create_token(Token::Tag, ss[1], line, str.length) : nil references << [:dollar, "$", tag, str.length, str.length + ss[0].length - 1] when ss.scan(/\$(<[a-zA-Z0-9_]+>)?(\d+)/) # $1, $2, $1 tag = ss[1] ? create_token(Token::Tag, ss[1], line, str.length) : nil references << [:dollar, Integer(ss[2]), tag, str.length, str.length + ss[0].length - 1] - when ss.scan(/\$(<[a-zA-Z0-9_]+>)?([a-zA-Z_.][-a-zA-Z0-9_.]*)/) # $foo, $expr, $program + when ss.scan(/\$(<[a-zA-Z0-9_]+>)?([a-zA-Z_][a-zA-Z0-9_]*)/) # $foo, $expr, $program (named reference without brackets) + tag = ss[1] ? create_token(Token::Tag, ss[1], line, str.length) : nil + references << [:dollar, ss[2], tag, str.length, str.length + ss[0].length - 1] + when ss.scan(/\$(<[a-zA-Z0-9_]+>)?\[([a-zA-Z_.][-a-zA-Z0-9_.]*)\]/) # $expr.right, $expr-right, $program (named reference with brackets) tag = ss[1] ? create_token(Token::Tag, ss[1], line, str.length) : nil references << [:dollar, ss[2], tag, str.length, str.length + ss[0].length - 1] + + # @ references + # It need to wrap an identifier with brackets to use ".-" for identifiers when ss.scan(/@\$/) # @$ references << [:at, "$", nil, str.length, str.length + ss[0].length - 1] when ss.scan(/@(\d+)/) # @1 references << [:at, Integer(ss[1]), nil, str.length, str.length + ss[0].length - 1] - when ss.scan(/@([a-zA-Z_.][-a-zA-Z0-9_.]*)/) # @foo, @expr + when ss.scan(/@([a-zA-Z][a-zA-Z0-9_]*)/) # @foo, @expr (named reference without brackets) + references << [:at, ss[1], nil, str.length, str.length + ss[0].length - 1] + when ss.scan(/@\[([a-zA-Z_.][-a-zA-Z0-9_.]*)\]/) # @expr.right, @expr-right (named reference with brackets) references << [:at, ss[1], nil, str.length, str.length + ss[0].length - 1] + when ss.scan(/{/) brace_count += 1 when ss.scan(/}/) diff --git a/lib/lrama/lexer/token.rb b/lib/lrama/lexer/token.rb index 4eca6f60..6221abe0 100644 --- a/lib/lrama/lexer/token.rb +++ b/lib/lrama/lexer/token.rb @@ -28,6 +28,7 @@ def numberize_references(lhs, rhs) if lhs.referred_by?(ref_name) '$' else + # TODO: Better error message for wrong reference rhs.find_index {|token| token.referred_by?(ref_name) } + 1 end [ref[0], value, ref[2], ref[3], ref[4]] diff --git a/spec/lrama/integration_spec.rb b/spec/lrama/integration_spec.rb index 5f83c3db..a3b22bb9 100644 --- a/spec/lrama/integration_spec.rb +++ b/spec/lrama/integration_spec.rb @@ -214,7 +214,7 @@ def test_rules(rules, input, expected, command_args: [], debug: false) ] cases = generate_lexer_body(input) - test_grammar(<<~Grammar, "expr[left]: 0.0-0.1. expr[right]: 1.0-1.1. line: 0.0-2.1. => 3") + test_grammar(<<~Grammar, "expr[ex-left] (0): 0.0-0.1. expr[ex.right] (1): 1.0-1.1. line (0): 0.0-2.1. => 3") %{ #include @@ -264,7 +264,7 @@ def test_rules(rules, input, expected, command_args: [], debug: false) { (void)yynerrs; - printf("line: "); + printf("line (%d): ", @expr.first_line); print_location(&@expr); printf("=> %d", $expr); @@ -272,15 +272,15 @@ def test_rules(rules, input, expected, command_args: [], debug: false) ; expr[result]: NUM - | expr[left] expr[right] '+' + | expr[ex-left] expr[ex.right] '+' { - printf("expr[left]: "); - print_location(&@left); + printf("expr[ex-left] (%d): ", @[ex-left].first_line); + print_location(&@[ex-left]); - printf("expr[right]: "); - print_location(&@right); + printf("expr[ex.right] (%d): ", @[ex.right].first_line); + print_location(&@[ex.right]); - $result = $left + $right; + $result = $[ex-left] + $[ex.right]; } ;