Nie masz niejasności. Świadczy o tym fakt, że standardowy analizator Go to LALR (1).
to nazwa typu lub nazwa zmiennej o większej liczbie zmiennych?
Więc twoja gramatyka i parser jako całość powinny być całkowicie odłączone od tablicy symboli; nie być C – Twoja gramatyka nie jest niejednoznaczna, dlatego możesz sprawdzić nazwę typu później w AST.
Oto odpowiednie zasady (od http://golang.org/ref/spec); są już poprawne.
Parameters = "(" [ ParameterList [ "," ] ] ")" .
ParameterList = ParameterDecl { "," ParameterDecl } .
ParameterDecl = [ IdentifierList ] [ "..." ] Type .
IdentifierList = identifier { "," identifier } .
Wytłumaczę ci je:
IdentifierList = identifier { "," identifier } .
Nawiasy klamrowe reprezentują KLEENE-zamknięcie (POSIX notacji wyrażenie regularne to gwiazdka). Zasada ta mówi, „an nazwa identyfikatora, a następnie ewentualnie dosłownym przecinkiem i identyfikator, a następnie ewentualnie dosłownym przecinkiem i identyfikator itp & hellip; ad infinitum”
ParameterDecl = [ IdentifierList ] [ "..." ] Type .
nawiasach kwadratowych są wartości null; oznacza to, że ta część może być obecna lub nie. (W notacji regularnej POSIX jest to znak zapytania). Więc trzeba „Może IdentifierList, a następnie być może wielokropkiem, a następnie typu.
ParameterList = ParameterDecl { "," ParameterDecl } .
Możesz mieć kilka ParameterDecl w liście, jak np func x(a, b int, c, d string)
.
Parameters = "(" [ ParameterList [ "," ] ] ")" .
Te zasady określa, że ParameterList jest opcjonalny i może być otoczony przez nawias i może zawierać opcjonalny końcowy przecinek dosłowne, przydatna, gdy piszesz coś takiego:
func x(
a, b int,
c, d string, // <- note the final comma
)
GO gramma r jest przenośny i może być przetwarzany przez każdy parownik bottom-up z jednym znacznikiem z wyprzedzeniem.
Edit dotyczące „nie bądź C”: Powiedziałem to, bo C is context-sensitive i sposobu ich rozwiązywania tego problemu w wielu (wszystkich?) Kompilatorów jest przez okablowanie tablicę symboli do lexer i Lexing tokeny inaczej w zależności od tego, czy są zdefiniowane jako nazwy lub zmienne. To jest hackowanie i nie powinno się tego robić dla jednoznacznych gramatyk!
Jak wygląda twoja gramatyka? – thwd
@tomwilde: Edytowałem post z odpowiednimi informacjami. Kod ma taką samą strukturę jak specyfikacja. – gnuvince
Myślę, że najprostszym podejściem jest traktowanie dowolnego odstępu (bez przecinka) jako tokenu typu wstępnego. Token po spacji (i może być tylko jedno miejsce bez przecinka) musi być typem. Jeśli token przed spacją nie pasuje do żadnego typu w bieżącym zakresie lub typu wbudowanego, musi to być zmienna nazwana. To prawdopodobnie zbyt naiwne. – Intermernet