0

I am using lark to parse some text and needed a way to match a NAME that did not have certain keywords in it. I have the keywords listed out in a terminal I am just not sure how to make the terminal I need using it.

Here is the way I formatted my keywords

keywords: "var"
        | "let"
        | "type"

All help on this is appreciated!

Asra
  • 151
  • 1
  • 11

1 Answers1

2

Lark has a built-in support for the concept of keywords. So, it is unlikely that you need to explicitly exclude keywords NAME.

For example:

l = Lark("""
    %import common (LETTER, DIGIT)
    NAME: LETTER (LETTER | DIGIT)*
    keywords: "var"
            | "let"
            | "type"

    start: NAME | keywords
""", parser="lalr")

print(l.parse("hello"))     # Tree('start', [Token('NAME', 'hello')])
print(l.parse("let"))       # Tree('start', [Tree('keywords', [])])

Having said that, if you must, you can accomplish this by using a regexp:

l = Lark("""
    %import common (LETTER, DIGIT)
    NAME: /(?!(let|type|var))/ LETTER (LETTER | DIGIT)*
    start: NAME
""")

print(l.parse("hello"))     # Tree('start', [Token('NAME', 'hello')])
print(l.parse("let"))       # Exception, terminal not defined

P.S. keep in mind that "TERMINAL" is upper-case, and "rule" is lower-case, and they have behave differently in Lark, so it's important to keep the distinction in mind.

Erez
  • 1,287
  • 12
  • 18
  • For the second one, is there any way to do that without having to manually type out each keyword? – Asra Mar 11 '21 at 05:16
  • Lark doesn't have such a feature, but it's fairly easy to do in code, since the grammar is just a string. – Erez Mar 12 '21 at 23:27
  • Ah ok, I am using an external file but thank you so much for the help, I'll test this out and make sure that mark it as correct if it works! – Asra Mar 13 '21 at 06:08
  • Ok, I have found a problem, I have a list is extensive keywords that I am using and the NAME definition looks like this `NAME: /(?!(let|type|var|alias|for|in|import|imp|return|if|else|class|pub|break|continue|with|yield|do|not))/ LETTER (LETTER | DIGIT)*`, for some reason this does not match to the value `int` – Asra Mar 13 '21 at 06:12
  • 1
    Ok I got it I just changed it to `NAME: /(?!(\b(let|type|var|alias|for|in|import|imp|return|if|else|class|pub|break|continue|with|yield|do|not)\b))/ LETTER (LETTER | DIGIT)*` – Asra Mar 13 '21 at 06:25