diff options
Diffstat (limited to 'src/urubu/spec/grammar.go')
-rw-r--r-- | src/urubu/spec/grammar.go | 251 |
1 files changed, 251 insertions, 0 deletions
diff --git a/src/urubu/spec/grammar.go b/src/urubu/spec/grammar.go new file mode 100644 index 0000000..c2708d8 --- /dev/null +++ b/src/urubu/spec/grammar.go @@ -0,0 +1,251 @@ +package grammar + +import ( + "strconv" + "strings" +) + +type Terminal struct { + Number int `json:"number"` + Name string `json:"name"` + Pattern string `json:"pattern"` + Precedence int `json:"prec"` + Associativity string `json:"assoc"` +} + +type NonTerminal struct { + Number int `json:"number"` + Name string `json:"name"` +} + +type Production struct { + Number int `json:"number"` + LHS int `json:"lhs"` + RHS []int `json:"rhs"` + Precedence int `json:"prec"` + Associativity string `json:"assoc"` +} + +type Item struct { + Production int `json:"production"` + Dot int `json:"dot"` +} + +type Transition struct { + Symbol int `json:"symbol"` + State int `json:"state"` +} + +type Reduce struct { + LookAhead []int `json:"look_ahead"` + Production int `json:"production"` +} + +type SRConflict struct { + Symbol int `json:"symbol"` + State int `json:"state"` + Production int `json:"production"` + AdoptedState *int `json:"adopted_state"` + AdoptedProduction *int `json:"adopted_production"` + ResolvedBy int `json:"resolved_by"` +} + +type RRConflict struct { + Symbol int `json:"symbol"` + Production1 int `json:"production_1"` + Production2 int `json:"production_2"` + AdoptedProduction int `json:"adopted_production"` + ResolvedBy int `json:"resolved_by"` +} + +type State struct { + Number int `json:"number"` + Kernel []*Item `json:"kernel"` + Shift []*Transition `json:"shift"` + Reduce []*Reduce `json:"reduce"` + GoTo []*Transition `json:"goto"` + SRConflict []*SRConflict `json:"sr_conflict"` + RRConflict []*RRConflict `json:"rr_conflict"` +} + +type Report struct { + Terminals []*Terminal `json:"terminals"` + NonTerminals []*NonTerminal `json:"non_terminals"` + Productions []*Production `json:"productions"` + States []*State `json:"states"` +} + +type CompiledGrammar struct { + Name string `json:"name"` + Lexical *LexicalSpec `json:"lexical"` + Syntactic *SyntacticSpec `json:"syntactic"` + ASTAction *ASTAction `json:"ast_action"` +} + +// StateID represents an ID of a state of a transition table. +type StateID int + +const ( + // StateIDNil represents an empty entry of a transition table. + // When the driver reads this value, it raises an error meaning lexical analysis failed. + StateIDNil = StateID(0) + + // StateIDMin is the minimum value of the state ID. All valid state IDs are represented as + // sequential numbers starting from this value. + StateIDMin = StateID(1) +) + +func (id StateID) Int() int { + return int(id) +} + +// LexModeID represents an ID of a lex mode. +type LexModeID int + +const ( + LexModeIDNil = LexModeID(0) + LexModeIDDefault = LexModeID(1) +) + +func (n LexModeID) String() string { + return strconv.Itoa(int(n)) +} + +func (n LexModeID) Int() int { + return int(n) +} + +func (n LexModeID) IsNil() bool { + return n == LexModeIDNil +} + +// LexModeName represents a name of a lex mode. +type LexModeName string + +const ( + LexModeNameNil = LexModeName("") + LexModeNameDefault = LexModeName("default") +) + +func (m LexModeName) String() string { + return string(m) +} + +// LexKindID represents an ID of a lexical kind and is unique across all modes. +type LexKindID int + +const ( + LexKindIDNil = LexKindID(0) + LexKindIDMin = LexKindID(1) +) + +func (id LexKindID) Int() int { + return int(id) +} + +// LexModeKindID represents an ID of a lexical kind and is unique within a mode. +// Use LexKindID to identify a kind across all modes uniquely. +type LexModeKindID int + +const ( + LexModeKindIDNil = LexModeKindID(0) + LexModeKindIDMin = LexModeKindID(1) +) + +func (id LexModeKindID) Int() int { + return int(id) +} + +// LexKindName represents a name of a lexical kind. +type LexKindName string + +const LexKindNameNil = LexKindName("") + +func (k LexKindName) String() string { + return string(k) +} + +type RowDisplacementTable struct { + OriginalRowCount int `json:"original_row_count"` + OriginalColCount int `json:"original_col_count"` + EmptyValue StateID `json:"empty_value"` + Entries []StateID `json:"entries"` + Bounds []int `json:"bounds"` + RowDisplacement []int `json:"row_displacement"` +} + +type UniqueEntriesTable struct { + UniqueEntries *RowDisplacementTable `json:"unique_entries,omitempty"` + UncompressedUniqueEntries []StateID `json:"uncompressed_unique_entries,omitempty"` + RowNums []int `json:"row_nums"` + OriginalRowCount int `json:"original_row_count"` + OriginalColCount int `json:"original_col_count"` + EmptyValue int `json:"empty_value"` +} + +type TransitionTable struct { + InitialStateID StateID `json:"initial_state_id"` + AcceptingStates []LexModeKindID `json:"accepting_states"` + RowCount int `json:"row_count"` + ColCount int `json:"col_count"` + Transition *UniqueEntriesTable `json:"transition,omitempty"` + UncompressedTransition []StateID `json:"uncompressed_transition,omitempty"` +} + +type CompiledLexModeSpec struct { + KindNames []LexKindName `json:"kind_names"` + Push []LexModeID `json:"push"` + Pop []int `json:"pop"` + DFA *TransitionTable `json:"dfa"` +} + +type LexicalSpec struct { + InitialModeID LexModeID `json:"initial_mode_id"` + ModeNames []LexModeName `json:"mode_names"` + KindNames []LexKindName `json:"kind_names"` + KindIDs [][]LexKindID `json:"kind_ids"` + CompressionLevel int `json:"compression_level"` + Specs []*CompiledLexModeSpec `json:"specs"` +} + +type SyntacticSpec struct { + Action []int `json:"action"` + GoTo []int `json:"goto"` + StateCount int `json:"state_count"` + InitialState int `json:"initial_state"` + StartProduction int `json:"start_production"` + LHSSymbols []int `json:"lhs_symbols"` + AlternativeSymbolCounts []int `json:"alternative_symbol_counts"` + Terminals []string `json:"terminals"` + TerminalCount int `json:"terminal_count"` + TerminalSkip []int `json:"terminal_skip"` + KindToTerminal []int `json:"kind_to_terminal"` + NonTerminals []string `json:"non_terminals"` + NonTerminalCount int `json:"non_terminal_count"` + EOFSymbol int `json:"eof_symbol"` + ErrorSymbol int `json:"error_symbol"` + ErrorTrapperStates []int `json:"error_trapper_states"` + RecoverProductions []int `json:"recover_productions"` +} + +type ASTAction struct { + Entries [][]int `json:"entries"` +} + +var rep = strings.NewReplacer( + `.`, `\.`, + `*`, `\*`, + `+`, `\+`, + `?`, `\?`, + `|`, `\|`, + `(`, `\(`, + `)`, `\)`, + `[`, `\[`, + `\`, `\\`, +) + +// EscapePattern escapes the special characters. +// For example, EscapePattern(`+`) returns `\+`. +func EscapePattern(s string) string { + return rep.Replace(s) +} |