public string GenerateCode(Skeleton skeleton, string generatorVersion) { var template = skeleton.Template; var equivalenceClassDataType = GenDataType(skeleton, equivalenceTable.Max(ec => ec.Value)); template = Replace(template, "EquivalenceClassType", equivalenceClassDataType); template = Replace(template, "GeneratorVersion", generatorVersion); template = Replace(template, "ClassName", lexerSpec.LexerName ?? "Lexer"); template = Replace(template, "ClassNamespace", lexerSpec.LexerNamespace); template = Replace(template, "Channels", GenChannels()); template = Replace(template, "TokenTypes", GenTokenTypes()); template = Replace(template, "Modes", GetModes()); template = Replace(template, "InitialMode", lexerSpec.InitialMode.ToString()); template = Replace(template, "ErrorState", errorState.ToString()); template = Replace(template, "PlaneOffsets", GenPlaneOffsets(skeleton).ToList()); template = Replace(template, "EquivalenceClassCases", GenEquivalenceClassCases().ToList()); template = Replace(template, "EquivalenceTable", GenEquivalenceTable()); template = Replace(template, "RowMapType", GenDataType(skeleton, rowMap.Max())); template = Replace(template, "RowMap", GenInts(rowMap)); template = Replace(template, "StateType", GenDataType(skeleton, transitions.Max())); // TODO need to create an error state so that we don't need to put negative values in the table template = Replace(template, "Transitions", GenInts(transitions)); template = Replace(template, "ActionMapType", GenDataType(skeleton, actionMap.Max())); template = Replace(template, "ActionMap", GenInts(actionMap)); template = Replace(template, "Actions", GenActions(skeleton).ToList()); return template; }
public string FileName(Skeleton skeleton) { return Path.ChangeExtension(lexerSpec.LexerName, skeleton.Extension); }
private IEnumerable<string> GenActions(Skeleton skeleton) { yield return "case 0:"; yield return " continue;"; for(var i = 1; i < actions.Length; i++) { var action = actions[i]; yield return $"case {i}:"; // Lexer Input Action DecodeValue decodeAction; TextValue valueAction; if(action.ValueAction == LexerValueAction.Capture) yield return " captureBuffer.Append(tokenBuffer.ToString());"; else if((decodeAction = action.ValueAction as DecodeValue) != null) yield return $" captureBuffer.Append(Decode(tokenBuffer.ToString(), {decodeAction.Base}));"; else if((valueAction = action.ValueAction as TextValue) != null) yield return $" tokenBuffer.Append(\"{valueAction.Value}\");"; else if(action.ValueAction == LexerValueAction.Ignore) { // Nothing to do on ignore } else throw new NotSupportedException($"Unsupported LexerValueAction type '{action.ValueAction.GetType().FullName}'"); foreach(var modeAction in action.ModeActions) { if(modeAction == LexerModeAction.Pop) yield return " currentMode = modeStack.Pop();"; else if(modeAction == LexerModeAction.Push) yield return " modeStack.Push(currentMode);"; else { var mode = ((SetMode)modeAction).Mode; yield return $" currentMode = Mode.{mode};"; } } EmitToken emitAction; if((emitAction = action.EmitAction as EmitToken) != null) { yield return $" token = new Adamant.CompilerCompiler.Lex.Runtime.Token<Channel, TokenType>(Channel.{emitAction.Channel}, TokenType.{emitAction.TokenType}, false, default(Adamant.CompilerCompiler.Lex.Runtime.FilePosition), default(Adamant.CompilerCompiler.Lex.Runtime.FilePosition), captureBuffer.ToString());"; } if(action.Code != null) yield return action.Code; yield return " break;"; } }
private IEnumerable<string> GenPlaneOffsets(Skeleton skeleton) { foreach(var planeOffset in planeOffsets) { if(planeOffset.Value.Length == 1) continue; var dataType = GenDataType(skeleton, planeOffset.Value.Max()); yield return $"private static readonly {dataType}[] plane{planeOffset.Key}Offsets ="; yield return "{"; foreach(var line in GenCommaSeparatedLines(planeOffset.Value.Select(v => v.ToString()))) yield return "\t" + line; yield return "};"; } }
private static string GenDataType(Skeleton skeleton, int value) { return skeleton.DataTypes.OrderBy(dt => dt.Bits).First(dt => value <= Math.Pow(2, dt.Bits)).Name; }